{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b8a61b26e03b962a",
   "metadata": {},
   "source": [
    "# Transformer Machine Translation\n",
    "在本项目中，我们将使用Transformer模型来实现机器翻译任务。\n",
    "手动搭建各个框架，并实现训练、推理、评估等功能，是一项复杂的任务。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b31f2c5f3d074412",
   "metadata": {},
   "source": [
    "## 导入环境"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "initial_id",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T09:12:52.176915Z",
     "start_time": "2025-03-13T09:12:52.166348Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:36.777501Z",
     "iopub.status.busy": "2025-03-13T12:13:36.777212Z",
     "iopub.status.idle": "2025-03-13T12:13:38.900942Z",
     "shell.execute_reply": "2025-03-13T12:13:38.900410Z",
     "shell.execute_reply.started": "2025-03-13T12:13:36.777467Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
      "  from .autonotebook import tqdm as notebook_tqdm\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=10, micro=14, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.1\n",
      "torch 2.5.1+cu124\n",
      "cuda:0\n"
     ]
    }
   ],
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "\n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 233\n",
    "torch.manual_seed(seed)\n",
    "torch.cuda.manual_seed_all(seed)\n",
    "np.random.seed(seed)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "495cbb63c8245171",
   "metadata": {},
   "source": [
    "## 数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "62e73d9cba754dd8",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T09:16:08.441328Z",
     "start_time": "2025-03-13T09:15:47.091985Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:38.902490Z",
     "iopub.status.busy": "2025-03-13T12:13:38.902121Z",
     "iopub.status.idle": "2025-03-13T12:13:38.904945Z",
     "shell.execute_reply": "2025-03-13T12:13:38.904460Z",
     "shell.execute_reply.started": "2025-03-13T12:13:38.902468Z"
    }
   },
   "outputs": [],
   "source": [
    "#!sh data_multi30k.sh wmt16 wmt16_cut de en"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8d635c6c2005c388",
   "metadata": {},
   "source": [
    "[train] 源语言文本分词完成\n",
    "[train] 目标语言文本分词完成\n",
    "[val] 源语言文本分词完成\n",
    "[val] 目标语言文本分词完成\n",
    "[test] 源语言文本分词完成\n",
    "[test] 目标语言文本分词完成\n",
    "Finished applying bpe to train files.\n",
    "Finished applying bpe to val files.\n",
    "Finished applying bpe to test files.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "be201fefc5cd49df",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T09:19:33.344433Z",
     "start_time": "2025-03-13T09:19:33.318996Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:38.905703Z",
     "iopub.status.busy": "2025-03-13T12:13:38.905531Z",
     "iopub.status.idle": "2025-03-13T12:13:38.988029Z",
     "shell.execute_reply": "2025-03-13T12:13:38.987511Z",
     "shell.execute_reply.started": "2025-03-13T12:13:38.905684Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "save cache to wmt16/.cache/de2en_train_128.npy\n",
      "save cache to wmt16/.cache/de2en_val_128.npy\n"
     ]
    }
   ],
   "source": [
    "from pathlib import Path\n",
    "from torch.utils.data import Dataset, DataLoader\n",
    "\n",
    "\n",
    "# 定义数据集\n",
    "class LangPairDataset(Dataset):\n",
    "\n",
    "    def __init__(\n",
    "        self, mode=\"train\", max_length=128, overwrite_cache=False, data_dir=\"wmt16\",\n",
    "    ):\n",
    "        self.data_dir = Path(data_dir)\n",
    "        cache_path = self.data_dir / \".cache\" / f\"de2en_{mode}_{max_length}.npy\"\n",
    "\n",
    "        if overwrite_cache or not cache_path.exists():\n",
    "            cache_path.parent.mkdir(parents=True, exist_ok=True) # 创建缓存目录\n",
    "\n",
    "            with open(self.data_dir / f\"{mode}_src.bpe\", \"r\", encoding=\"utf8\") as file:\n",
    "                self.src = file.readlines() # 读取源语言文件所有行\n",
    "\n",
    "            with open(self.data_dir / f\"{mode}_trg.bpe\", \"r\", encoding=\"utf8\") as file:\n",
    "                self.trg = file.readlines() # 读取目标语言文件所有行\n",
    "\n",
    "            filtered_src = []\n",
    "            filtered_trg = []\n",
    "            # max length filter,超出最大长度的句子舍弃\n",
    "            for src, trg in zip(self.src, self.trg):\n",
    "                if len(src) <= max_length and len(trg) <= max_length: # 过滤长度超过最大长度的句子\n",
    "                    filtered_src.append(src.strip()) # 去掉句子前后的空格\n",
    "                    filtered_trg.append(trg.strip())\n",
    "            filtered_src = np.array(filtered_src)\n",
    "            filtered_trg = np.array(filtered_trg)\n",
    "            np.save(\n",
    "                cache_path,\n",
    "                {\"src\": filtered_src, \"trg\": filtered_trg },\n",
    "                allow_pickle=True,\n",
    "            )#allow_pickle=True允许保存对象数组，将过滤后的数据保存为 NumPy 数组，存储在缓存文件中\n",
    "            print(f\"save cache to {cache_path}\")\n",
    "\n",
    "        else:\n",
    "            cache_dict = np.load(cache_path, allow_pickle=True).item() #allow_pickle=True允许保存对象数组\n",
    "            print(f\"load {mode} dataset from {cache_path}\")\n",
    "            filtered_src = cache_dict[\"src\"]\n",
    "            filtered_trg = cache_dict[\"trg\"]\n",
    "\n",
    "        self.src = filtered_src\n",
    "        self.trg = filtered_trg\n",
    "\n",
    "    def __getitem__(self, index):\n",
    "        return self.src[index], self.trg[index]\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.src)\n",
    "\n",
    "\n",
    "train_ds = LangPairDataset(\"train\")\n",
    "val_ds = LangPairDataset(\"val\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "91aa3a1cd0bd7c44",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T09:20:00.176309Z",
     "start_time": "2025-03-13T09:20:00.101132Z"
    },
    "ExecutionIndicator": {
     "show": true
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:38.988876Z",
     "iopub.status.busy": "2025-03-13T12:13:38.988628Z",
     "iopub.status.idle": "2025-03-13T12:13:39.111029Z",
     "shell.execute_reply": "2025-03-13T12:13:39.110407Z",
     "shell.execute_reply.started": "2025-03-13T12:13:38.988856Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "!rm wmt16/.cache -r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "de2d01c25647d9b6",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T09:20:46.712973Z",
     "start_time": "2025-03-13T09:20:46.708945Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.111990Z",
     "iopub.status.busy": "2025-03-13T12:13:39.111734Z",
     "iopub.status.idle": "2025-03-13T12:13:39.115315Z",
     "shell.execute_reply": "2025-03-13T12:13:39.114829Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.111969Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "source: ein älterer mann sitzt mit einem jungen mit einem wagen vor einer fassade .\n",
      "target: an elderly man sits outside a storefront accompanied by a young boy with a cart .\n"
     ]
    }
   ],
   "source": [
    "# 测试数据集\n",
    "print(\"source: {}\\ntarget: {}\".format(*train_ds[-1]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9babc7aa96378d0",
   "metadata": {},
   "source": [
    "## Tokenizer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e4688a652117ee7a",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T09:21:46.769419Z",
     "start_time": "2025-03-13T09:21:46.740860Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.116143Z",
     "iopub.status.busy": "2025-03-13T12:13:39.115922Z",
     "iopub.status.idle": "2025-03-13T12:13:39.142277Z",
     "shell.execute_reply": "2025-03-13T12:13:39.141816Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.116124Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 18107/18107 [00:00<00:00, 1014117.73it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "vocab_size: 18111\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "#载入词表，看下词表长度，词表就像英语字典,构建word2idx和idx2word\n",
    "word2idx = {\n",
    "    \"[PAD]\": 0,     # 填充 token\n",
    "    \"[BOS]\": 1,     # begin of sentence\n",
    "    \"[UNK]\": 2,     # 未知 token\n",
    "    \"[EOS]\": 3,     # end of sentence\n",
    "}\n",
    "idx2word = {value: key for key, value in word2idx.items()}\n",
    "index = len(idx2word)\n",
    "threshold = 1  # 出现次数低于此的token舍弃\n",
    "\n",
    "with open(\"wmt16/vocab\", \"r\", encoding=\"utf8\") as file:\n",
    "    for line in tqdm(file.readlines()):\n",
    "        token, counts = line.strip().split()\n",
    "        if int(counts) >= threshold:\n",
    "            word2idx[token] = index\n",
    "            idx2word[index] = token\n",
    "            index += 1\n",
    "\n",
    "vocab_size = len(word2idx)\n",
    "# 打印词表的size\n",
    "print(\"vocab_size: {}\".format(vocab_size))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "74c349611fd88de2",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T09:22:35.717588Z",
     "start_time": "2025-03-13T09:22:35.670058Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.144368Z",
     "iopub.status.busy": "2025-03-13T12:13:39.144049Z",
     "iopub.status.idle": "2025-03-13T12:13:39.156365Z",
     "shell.execute_reply": "2025-03-13T12:13:39.155905Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.144348Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "raw text\n",
      "['hello', 'world']\n",
      "['tokenize', 'text', 'datas', 'with', 'batch']\n",
      "['this', 'is', 'a', 'test']\n",
      "indices\n",
      "tensor([   1, 9458, 3522,    3,    0,    0,    0])\n",
      "tensor([   1,    2, 5463,    2,   22,    2,    3])\n",
      "tensor([   1,  385,   18,    5, 5699,    3,    0])\n",
      "decode text\n",
      "[BOS] hello world [EOS] [PAD] [PAD] [PAD]\n",
      "[BOS] [UNK] text [UNK] with [UNK] [EOS]\n",
      "[BOS] this is a test [EOS] [PAD]\n"
     ]
    }
   ],
   "source": [
    "class Tokenizer:\n",
    "    def __init__(self, word2idx, idx2word, max_length=128, pad_idx=0, bos_idx=1, eos_idx=3, unk_idx=2):\n",
    "        self.word2idx = word2idx    # 词到索引的映射\n",
    "        self.idx2word = idx2word    # 索引到词的映射\n",
    "        self.max_length = max_length    # 句子最大长度\n",
    "        self.pad_idx = pad_idx        # padding token的索引\n",
    "        self.bos_idx = bos_idx        # begin of sentence token的索引\n",
    "        self.eos_idx = eos_idx        # end of sentence token的索引\n",
    "        self.unk_idx = unk_idx        # unknown token的索引\n",
    "\n",
    "    def encode(self, text_list, padding_first=False, add_bos=True, add_eos=True, return_mask=False):\n",
    "        \"\"\"如果padding_first == True，则padding加载前面，否则加载后面\"\"\"\n",
    "        max_length = min(self.max_length, add_eos + add_bos + max([len(text) for text in text_list]))\n",
    "        indices_list = []\n",
    "        for text in text_list:\n",
    "            indices = [self.word2idx.get(word, self.unk_idx) for word in text[:max_length - add_bos - add_eos]]\n",
    "            if add_bos:\n",
    "                indices = [self.bos_idx] + indices\n",
    "            if add_eos:\n",
    "                indices = indices + [self.eos_idx]\n",
    "            if padding_first:\n",
    "                indices = [self.pad_idx] * (max_length - len(indices)) + indices\n",
    "            else:\n",
    "                indices = indices + [self.pad_idx] * (max_length - len(indices))\n",
    "            indices_list.append(indices)\n",
    "        input_ids = torch.tensor(indices_list)\n",
    "        masks = (input_ids == self.pad_idx).to(dtype=torch.int64) # 为了方便损失计算，这里的mask为0的地方需要计算，为1的地方不需要计算\n",
    "        return input_ids if not return_mask else (input_ids, masks)\n",
    "\n",
    "\n",
    "    def decode(self, indices_list, remove_bos=True, remove_eos=True, remove_pad=True, split=False):\n",
    "        text_list = []\n",
    "        for indices in indices_list:\n",
    "            text = []\n",
    "            for index in indices:\n",
    "                word = self.idx2word.get(index, \"[UNK]\")\n",
    "                if remove_bos and word == \"[BOS]\":\n",
    "                    continue\n",
    "                if remove_eos and word == \"[EOS]\":\n",
    "                    break\n",
    "                if remove_pad and word == \"[PAD]\":\n",
    "                    break\n",
    "                text.append(word)\n",
    "            text_list.append(\" \".join(text) if not split else text)\n",
    "        return text_list\n",
    "\n",
    "\n",
    "tokenizer = Tokenizer(word2idx=word2idx, idx2word=idx2word)\n",
    "\n",
    "\n",
    "raw_text = [\"hello world\".split(), \"tokenize text datas with batch\".split(), \"this is a test\".split()]\n",
    "indices = tokenizer.encode(raw_text, padding_first=False, add_bos=True, add_eos=True)\n",
    "decode_text = tokenizer.decode(indices.tolist(), remove_bos=False, remove_eos=False, remove_pad=False)\n",
    "# 打印原始文本、编码后文本、解码后文本,是为了测试\n",
    "print(\"raw text\")\n",
    "for raw in raw_text:\n",
    "    print(raw)\n",
    "print(\"indices\")\n",
    "for index in indices:\n",
    "    print(index)\n",
    "print(\"decode text\")\n",
    "for decode in decode_text:\n",
    "    print(decode)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76c36305c515daad",
   "metadata": {},
   "source": [
    "## "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c1457fe55de98542",
   "metadata": {},
   "source": [
    "## Batch Sampler"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "7871c644c0257db4",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T10:56:10.655223Z",
     "start_time": "2025-03-13T10:56:10.648969Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.157029Z",
     "iopub.status.busy": "2025-03-13T12:13:39.156865Z",
     "iopub.status.idle": "2025-03-13T12:13:39.163205Z",
     "shell.execute_reply": "2025-03-13T12:13:39.162690Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.157011Z"
    }
   },
   "outputs": [],
   "source": [
    "class SampleInfo: #下面的info对象\n",
    "    \"\"\"\n",
    "    该类实现了对文本对的长度信息的记录\n",
    "    \"\"\"\n",
    "    def __init__(self, i, lens):\n",
    "        \"\"\"\n",
    "        记录文本对的序号和长度信息\n",
    "        输入：\n",
    "            - i (int): 文本对的序号。\n",
    "            - lens (list): 文本对源语言和目标语言的长度\n",
    "        \"\"\"\n",
    "        self.i = i\n",
    "        # 加一是考虑填补在文本前后的特殊词元，lens[0]和lens[1]分别表示源语言和目标语言的长度\n",
    "        self.max_len = max(lens[0], lens[1]) + 1\n",
    "        self.src_len = lens[0] + 1\n",
    "        self.trg_len = lens[1] + 1\n",
    "\n",
    "# 一个批量生成器，根据词元数目的限制来控制批量的大小。它会根据传入的样本信息，在不超过设定大小的情况下，逐步构建批量。\n",
    "class TokenBatchCreator:\n",
    "    \"\"\"\n",
    "    该类实现了批量生成器，用于生成文本对的批量。\n",
    "    \"\"\"\n",
    "    def __init__(self, batch_size):\n",
    "        \"\"\"\n",
    "        参数:\n",
    "        batch_size (int): 用于限制批量的大小。\n",
    "        功能:\n",
    "        初始化了一个空的批量列表 _batch。\n",
    "        设定了初始的最大长度为 -1。\n",
    "        存储了传入的 batch_size。\n",
    "        \"\"\"\n",
    "\n",
    "        self._batch = []  #这个就是之前的batch_size，就是第一个batch内有多少个样本\n",
    "        self.max_len = -1\n",
    "        self._batch_size = batch_size # 限制批量的大小,假设是4096\n",
    "\n",
    "    def append(self, info: SampleInfo):\n",
    "        \"\"\"\n",
    "        参数:\n",
    "        info (SampleInfo): 文本对的信息。\n",
    "        功能:\n",
    "        接收一个 SampleInfo 对象，并根据其最大长度信息更新当前批量的最大长度。\n",
    "        如果将新的样本加入批量后超过了批量大小限制，它会返回已有的批量并将新的样本加入新的批量。\n",
    "        否则，它会更新最大长度并将样本添加到当前批量中。\n",
    "        \"\"\"\n",
    "        # 更新当前批量的最大长度\n",
    "        cur_len = info.max_len # 当前样本的长度\n",
    "        max_len = max(self.max_len, cur_len) # 每来一个样本，更新当前批次的最大长度\n",
    "        # 如果新的样本加入批量后超过大小限制，则将已有的批量返回，新的样本加入新的批量\n",
    "        if max_len * (len(self._batch) + 1) > self._batch_size:\n",
    "            self._batch, result = [], self._batch # 保存当前的batch，并返回,这里的result是之前的batch,_batch清空\n",
    "            self._batch.append(info) #箱子里的第一条样本，放入\n",
    "            self.max_len = cur_len #因为是当前batch的第一个样本，所以它的长度就是当前长度\n",
    "            return result\n",
    "        else:\n",
    "            self.max_len = max_len\n",
    "            self._batch.append(info) # 将样本添加到当前批量中\n",
    "            return None\n",
    "\n",
    "    @property\n",
    "    def batch(self):\n",
    "        return self._batch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "27cd69e4f2f95182",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T10:58:05.668897Z",
     "start_time": "2025-03-13T10:58:05.660706Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.164041Z",
     "iopub.status.busy": "2025-03-13T12:13:39.163834Z",
     "iopub.status.idle": "2025-03-13T12:13:39.171926Z",
     "shell.execute_reply": "2025-03-13T12:13:39.171457Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.164022Z"
    }
   },
   "outputs": [],
   "source": [
    "from torch.utils.data import BatchSampler\n",
    "import numpy as np\n",
    "\n",
    "# 继承BatchSampler，实现自己的BatchSampler\n",
    "class TransformerBatchSampler(BatchSampler):\n",
    "    def __init__(self,\n",
    "                 dataset,\n",
    "                 batch_size,\n",
    "                 shuffle_batch=False,\n",
    "                 clip_last_batch=False,\n",
    "                 seed=0):\n",
    "        \"\"\"\n",
    "        批量采样器\n",
    "        输入:\n",
    "            - dataset: 数据集\n",
    "            - batch_size: 批量大小\n",
    "            - shuffle_batch: 是否对生成的批量进行洗牌\n",
    "            - clip_last_batch: 是否裁剪最后剩下的数据\n",
    "            - seed: 随机数种子\n",
    "        \"\"\"\n",
    "        # super().__init__(dataset, batch_size, False) # 这里的False表示drop_last=False,即最后一个batch不一定是batch_size的整数倍\n",
    "        self._dataset = dataset\n",
    "        self._batch_size = batch_size\n",
    "        self._shuffle_batch = shuffle_batch\n",
    "        self._clip_last_batch = clip_last_batch\n",
    "        self._seed = seed #下面3个是为了随机\n",
    "        self._random = np.random\n",
    "        self._random.seed(seed)\n",
    "\n",
    "        self._sample_infos = []\n",
    "        # 根据数据集中的每个样本，创建了对应的 SampleInfo 对象，包含了样本的索引和长度信息。\n",
    "        for i, data in enumerate(self._dataset):\n",
    "            lens = [len(data[0]), len(data[1])] #输入和输出的长度计算放到lens中\n",
    "            self._sample_infos.append(SampleInfo(i, lens))\n",
    "\n",
    "    def __iter__(self):\n",
    "        \"\"\"\n",
    "        对数据集中的样本进行排序，排序规则是先按源语言长度排序，如果相同则按目标语言长度排序。\n",
    "        使用 TokenBatchCreator 逐步组装批量数据，当满足批量大小时返回一个批量的样本信息。\n",
    "        如果不裁剪最后一个批次的数据且存在剩余样本，则将这些样本组成最后一个批次。\n",
    "        如果需要对批量进行洗牌，则对批次进行洗牌操作。\n",
    "        通过迭代器，抛出每个批量的样本在数据集中的索引。\n",
    "        \"\"\"\n",
    "        # 排序，如果源语言长度相同则按照目标语言的长度排列\n",
    "        infos = sorted(self._sample_infos,\n",
    "                       key=lambda x: (x.src_len, x.trg_len))\n",
    "        # 把样本放入到箱子里，所有装箱后的箱子，每一个箱子都放入batch_infos\n",
    "        batch_infos = []\n",
    "        batch_creator = TokenBatchCreator(self._batch_size) # 批量生成器\n",
    "        for info in infos:\n",
    "            batch = batch_creator.append(info)\n",
    "            # 存够一个batch的样本信息后，会把这个batch返回，否则返回为None\n",
    "            if batch is not None:\n",
    "                batch_infos.append(batch)\n",
    "\n",
    "        # 是否抛弃最后批量的文本对\n",
    "        if not self._clip_last_batch and len(batch_creator.batch) != 0:\n",
    "            batch_infos.append(batch_creator.batch) # 最后一个batch\n",
    "\n",
    "        # 打乱batch，打乱的是箱子的顺序\n",
    "        if self._shuffle_batch:\n",
    "            self._random.shuffle(batch_infos)\n",
    "\n",
    "        self.batch_number = len(batch_infos)\n",
    "        # print(self.batch_number) #为了理解\n",
    "\n",
    "        # 抛出一个箱子里所有样本的序号\n",
    "        for batch in batch_infos:\n",
    "            batch_indices = [info.i for info in batch] # 批量的样本在数据集中的索引，第一个batch[0,1,.....82]，第二个batch[83,84,85,86,87]\n",
    "            yield batch_indices\n",
    "\n",
    "    def __len__(self):\n",
    "        \"\"\"\n",
    "        返回批量的数量\n",
    "        \"\"\"\n",
    "        if hasattr(self, \"batch_number\"):\n",
    "            return self.batch_number\n",
    "        # 计算批量的数量,没有用到下面的情况，不用看\n",
    "        batch_number = (len(self._dataset) +\n",
    "                        self._batch_size) // self._batch_size\n",
    "        return batch_number"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "f5902a2fc8518fc7",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T10:58:28.731425Z",
     "start_time": "2025-03-13T10:58:28.576802Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.172629Z",
     "iopub.status.busy": "2025-03-13T12:13:39.172463Z",
     "iopub.status.idle": "2025-03-13T12:13:39.317718Z",
     "shell.execute_reply": "2025-03-13T12:13:39.317143Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.172611Z"
    }
   },
   "outputs": [],
   "source": [
    "# 测试BatchSampler\n",
    "sampler = TransformerBatchSampler(train_ds, batch_size=4096, shuffle_batch=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "1052c0aba20182e7",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T10:58:34.906023Z",
     "start_time": "2025-03-13T10:58:34.874721Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.318586Z",
     "iopub.status.busy": "2025-03-13T12:13:39.318329Z",
     "iopub.status.idle": "2025-03-13T12:13:39.357631Z",
     "shell.execute_reply": "2025-03-13T12:13:39.357147Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.318566Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[26845, 982, 1864, 3222, 4716, 5341, 5897, 6103, 8531, 10067, 11125, 13063, 14929, 15158, 18063, 18502, 20661, 20986, 21320, 22030, 22882, 23567, 24909, 1881, 2268, 4268, 7413, 10166, 12447, 13573, 15332, 16727, 17657, 20829, 21508, 23094, 24274, 25801, 518, 2145, 4111, 4739, 4745, 7493, 7623, 8369, 8618, 8730, 9054, 9391, 9808, 10141, 10412, 11422, 13534, 15038]\n"
     ]
    }
   ],
   "source": [
    "for i, batch in enumerate(sampler):\n",
    "    if i == 0:\n",
    "        print(batch)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3db47551e955f8c5",
   "metadata": {},
   "source": [
    "## 实现data loader"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "31c4cba0637498ad",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T10:59:42.143107Z",
     "start_time": "2025-03-13T10:59:42.138524Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.358371Z",
     "iopub.status.busy": "2025-03-13T12:13:39.358198Z",
     "iopub.status.idle": "2025-03-13T12:13:39.363264Z",
     "shell.execute_reply": "2025-03-13T12:13:39.362751Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.358352Z"
    }
   },
   "outputs": [],
   "source": [
    "def collate_fct(batch, tokenizer):\n",
    "    \"\"\"\n",
    "    实现了 collate_fn 函数，用于将数据处理成模型可读的形式。\n",
    "    :param batch:    一个batch的数据\n",
    "    :param tokenizer:    tokenizer\n",
    "    :return:        处理好的batch数据\n",
    "    \"\"\"\n",
    "    src_words = [pair[0].split() for pair in batch]\n",
    "    trg_words = [pair[1].split() for pair in batch]\n",
    "\n",
    "    # [BOS] src [EOS] [PAD]\n",
    "    encoder_inputs, encoder_inputs_mask = tokenizer.encode(\n",
    "        src_words, padding_first=False, add_bos=True, add_eos=True, return_mask=True\n",
    "        )\n",
    "\n",
    "    # [BOS] trg [PAD]\n",
    "    decoder_inputs = tokenizer.encode(\n",
    "        trg_words, padding_first=False, add_bos=True, add_eos=False, return_mask=False,\n",
    "        )\n",
    "\n",
    "    # trg [EOS] [PAD]\n",
    "    decoder_labels, decoder_labels_mask = tokenizer.encode(\n",
    "        trg_words, padding_first=False, add_bos=False, add_eos=True, return_mask=True\n",
    "        )\n",
    "\n",
    "    return {\n",
    "        \"encoder_inputs\": encoder_inputs.to(device=device),\n",
    "        \"encoder_inputs_mask\": encoder_inputs_mask.to(device=device),\n",
    "        \"decoder_inputs\": decoder_inputs.to(device=device),\n",
    "        \"decoder_labels\": decoder_labels.to(device=device),\n",
    "        \"decoder_labels_mask\": decoder_labels_mask.to(device=device),\n",
    "    }\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "5bca5f051083ea79",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:00:16.079645Z",
     "start_time": "2025-03-13T11:00:15.790170Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.364028Z",
     "iopub.status.busy": "2025-03-13T12:13:39.363817Z",
     "iopub.status.idle": "2025-03-13T12:13:39.539107Z",
     "shell.execute_reply": "2025-03-13T12:13:39.538569Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.364010Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "encoder_inputs\n",
      "tensor([[    1,     7,    17,     6,  4636,  3116,    31, 13407,     4,     3,\n",
      "             0,     0,     0],\n",
      "        [    1,  1310,    12,  2275,  6752,  1029,  8834, 13522,     4,     3,\n",
      "             0,     0,     0],\n",
      "        [    1,    84,    58,   172,   288,     9,    29,    98,    12,    21,\n",
      "            52,     4,     3],\n",
      "        [    1,    17,     6,   488,   442,    12,   499,   199,    73,    11,\n",
      "           235,     4,     3]], device='cuda:0')\n",
      "encoder_inputs_mask\n",
      "tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],\n",
      "        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],\n",
      "        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n",
      "        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], device='cuda:0')\n",
      "decoder_inputs\n",
      "tensor([[   1,    5,  324,   36, 2123,  672,   18, 2497,    5, 3739, 2933,    4,\n",
      "            0,    0],\n",
      "        [   1,    5, 1270,   19, 2409,   30, 2698,  307,  136, 1213, 1174,    4,\n",
      "            0,    0],\n",
      "        [   1,   87,   51,   30,  242,    9,   28,   53,   19,   83,   62,    4,\n",
      "            0,    0],\n",
      "        [   1,    5,   16,   36,    5,   45,  362,   19,   55,   80,  265,    5,\n",
      "          219,    4]], device='cuda:0')\n",
      "decoder_labels\n",
      "tensor([[   5,  324,   36, 2123,  672,   18, 2497,    5, 3739, 2933,    4,    3,\n",
      "            0,    0],\n",
      "        [   5, 1270,   19, 2409,   30, 2698,  307,  136, 1213, 1174,    4,    3,\n",
      "            0,    0],\n",
      "        [  87,   51,   30,  242,    9,   28,   53,   19,   83,   62,    4,    3,\n",
      "            0,    0],\n",
      "        [   5,   16,   36,    5,   45,  362,   19,   55,   80,  265,    5,  219,\n",
      "            4,    3]], device='cuda:0')\n",
      "decoder_labels_mask\n",
      "tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],\n",
      "        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],\n",
      "        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],\n",
      "        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], device='cuda:0')\n"
     ]
    }
   ],
   "source": [
    "from functools import partial # 固定collate_fct的tokenizer参数\n",
    "\n",
    "#可以调大batch_size,来看最终的bleu，如果GPU内存不够，可以减小batch_size\n",
    "sampler = TransformerBatchSampler(train_ds, batch_size=256, shuffle_batch=True)\n",
    "# https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader\n",
    "sample_dl = DataLoader(train_ds, batch_sampler=sampler, collate_fn=partial(collate_fct, tokenizer=tokenizer)) #partial函数，固定collate_fct的tokenizer参数,是为了固定参数\n",
    "\n",
    "# 打印一个batch的数据\n",
    "for batch in sample_dl:#外层是拿每个batch\n",
    "    for key, value in batch.items():#内层是拿每个batch里面是一个字典\n",
    "        print(key)\n",
    "        print(value)\n",
    "    break"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8c9ca34cdbe14f33",
   "metadata": {},
   "source": [
    "## 构建Embedding层"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "713252f4cfd84a72",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:02:31.318026Z",
     "start_time": "2025-03-13T11:02:31.087163Z"
    },
    "ExecutionIndicator": {
     "show": true
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.540116Z",
     "iopub.status.busy": "2025-03-13T12:13:39.539800Z",
     "iopub.status.idle": "2025-03-13T12:13:39.709334Z",
     "shell.execute_reply": "2025-03-13T12:13:39.708853Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.540095Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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dVISv4Z43aR2NNrJyxtvvIGsrCxMmzYN69atQ48ePTB48OCTdvdryKxatQoTJkzA6tWrsWzZMlRUVOCiiy5CcXGxqjN58mS8//77ePPNN7Fq1Srs2bMHV111VRBHXbd88803eOGFF9C9e3dTeWO87sOHD+Pcc8+Fw+HAxx9/jJ9//hn//Oc/ERcXp+pUJyV9Q+PRRx/F888/j2effRYbN27Eo48+isceewzPPPOMqtMYrru4uBg9evTA3LlzfR6vzjWOHDkSGzZswLJly/DBBx/giy++wPjx48/UJQREVdddUlKCdevW4YEHHsC6devw9ttvY9OmTbj88stN9RridZNaUqNMSA2Ifv36GRMmTFA/ezweIzU11Zg1a1YQR3V62bdvnwHAWLVqlWEYhpGfn284HA7jzTffVHU2btxoADCys7ODNcw648iRI0b79u2NZcuWGX/84x+NO+64wzCMxnvd9957rzFgwAC/x71er5GcnGw8/vjjqiw/P99wuVzGv//97zMxxNPC0KFDjb/85S+msquuusoYOXKkYRiN87oBGO+88476uTrX+PPPPxsAjG+++UbV+fjjjw2LxWLs3r37jI29Npx43b5Yu3atAcDYsWOHYRiN47pJzWmUKy/l5eXIyckxpea2Wq3IzMxEdnZ2EEd2ejm+WVB8fDwAICcnBxUVFab70KlTJ7Rs2bJR3IcJEyZg6NChpusDGu91v/fee+jbty+uvvpqNG3aFL169cJLL72kjp8qJX1DpX///li+fDl+/fVXAMD333+PL7/8EhdffDGAxnvdOtW5xuzsbMTGxqJv376qTmZmJqxWK9asWXPGx3y6KCgogMViQWxsLIDQuW5ipt7vsBsIBw4cgMfjOWkX3qSkJPzyyy9BGtXpxev1YtKkSTj33HPRtWtXAEBubi6cTqf6JT9OUlIScnNzgzDKumPx4sVYt24dvvnmm5OONdbr/u233/D8888jKysLf/vb3/DNN9/g9ttvh9PpxOjRo9W1+frcN+Trvu+++1BYWIhOnTrBZrPB4/HgoYcewsiRIwGg0V63TnWuMTc3F02bNjUdt9vtiI+PbzT3obS0FPfeey+uu+46lZgxFK6bnEyjnLyEIhMmTMBPP/2EL7/8MthDOe3s2rULd9xxB5YtW3bGs7IGE6/Xi759++Lhhx8GcGy77p9++gnz5s3D6NGjgzy608d//vMfvP7661i0aBHOOussrF+/HpMmTUJqamqjvm5ipqKiAtdccw0Mw8Dzzz8f7OGQINMoHxs1adIENpvtJHdJXl5ejdNuNwQmTpyIDz74AJ9//jmaN2+uypOTk1FeXo78/HxT/YZ+H3JycrBv3z707t0bdrsddrsdq1atwpw5c2C325GUlNQorzslJQVdunQxlXXu3Bk7d+4EYE5Jr9PQr/vuu+/GfffdhxEjRqBbt27485//jMmTJ2PWrFkAGu9161TnGpOTk08yJFRWVuLQoUMN/j4cn7js2LEDy5YtU6suQOO+buKfRjl5cTqd6NOnD5YvX67KvF4vli9fjoyMjCCOrG4xDAMTJ07EO++8gxUrVqB169am43369IHD4TDdh02bNmHnzp0N+j4MGjQIP/74o8pyun79evTt2xcjR45UujFe97nnnnuSFf7XX39Fq1atAJhT0h/neEr6hnzdJSUlsFrNf6psNhu8Xi+AxnvdOtW5xoyMDOTn5yMnJ0fVWbFiBbxeL9LT08/4mOuK4xOXzZs347PPPkNCQoLpeGO9bnIKgh0xfLpYvHix4XK5jFdeecX4+eefjfHjxxuxsbFGbm5usIdWZ9xyyy1GTEyMsXLlSmPv3r3qVVJSourcfPPNRsuWLY0VK1YY3377rZGRkWFkZGQEcdSnB91tZBiN87rXrl1r2O1246GHHjI2b95svP7660Z4eLjxr3/9S9V55JFHjNjYWOPdd981fvjhB+OKK64wWrdubRw9ejSII68do0ePNpo1a2Z88MEHxrZt24y3337baNKkiXHPPfeoOo3huo8cOWJ89913xnfffWcAMJ588knju+++U66a6lzjkCFDjF69ehlr1qwxvvzyS6N9+/bGddddF6xLqhZVXXd5eblx+eWXG82bNzfWr19v+jtXVlam+miI101qR6OdvBiGYTzzzDNGy5YtDafTafTr189YvXp1sIdUpwDw+Vq4cKGqc/ToUePWW2814uLijPDwcOPKK6809u7dG7xBnyZOnLw01ut+//33ja5duxoul8vo1KmT8eKLL5qOe71e44EHHjCSkpIMl8tlDBo0yNi0aVOQRls3FBYWGnfccYfRsmVLw+12G23atDH+/ve/m/7zagzX/fnnn/v8fR49erRhGNW7xoMHDxrXXXedERkZaURHRxtjxowxjhw5EoSrqT5VXfe2bdv8/p37/PPPVR8N8bpJ7bAYhrZNJSGEEEJIPadRxrwQQgghpPHCyQshhBBCGhScvBBCCCGkQcHJCyGEEEIaFJy8EEIIIaRBwckLIYQQQhoUnLwQQgghpEHByQshpFps374dFosF69evD/ZQCCEhDicvhDQQbrzxRlgsFlgsFjgcDiQlJeHCCy/EggULVJ6fujzXsGHD6rRPQgipKzh5IaQBMWTIEOzduxfbt2/Hxx9/jAsuuAB33HEHLr30UlRWVgZ7eIQQckbg5IWQBoTL5UJycjKaNWuG3r17429/+xveffddfPzxx3jllVcAAPn5+bjpppuQmJiI6OhoDBw4EN9//73qY/r06ejZsydeeOEFtGjRAuHh4bjmmmtQUFCgjr/66qt499131UrPypUrVfvffvsNF1xwAcLDw9GjRw9kZ2efyVtACCGcvBDS0Bk4cCB69OiBt99+GwBw9dVXY9++ffj444+Rk5OD3r17Y9CgQTh06JBqs2XLFvznP//B+++/j6VLl+K7777DrbfeCgC46667cM0116hVnr1796J///6q7d///nfcddddWL9+PTp06IDrrruOqz6EkDMKJy+ENAI6deqE7du348svv8TatWvx5ptvom/fvmjfvj2eeOIJxMbG4q233lL1S0tL8dprr6Fnz54477zz8Mwzz2Dx4sXIzc1FZGQkwsLC1CpPcnIynE6nanvXXXdh6NCh6NChA2bMmIEdO3Zgy5YtwbhsQkiIwskLIY0AwzBgsVjw/fffo6ioCAkJCYiMjFSvbdu2YevWrap+y5Yt0axZM/VzRkYGvF4vNm3adMpzde/eXemUlBQAwL59++rwagghpGrswR4AIaT2bNy4Ea1bt0ZRURFSUlJMMSrHiY2NrZNzORwOpS0WCwDUuduJEEKqgpMXQho4K1aswI8//ojJkyejefPmyM3Nhd1uR1pamt82O3fuxJ49e5CamgoAWL16NaxWKzp27AgAcDqd8Hg8Z2L4hBBSYzh5IaQBUVZWhtzcXHg8HuTl5WHp0qWYNWsWLr30UowaNQpWqxUZGRkYNmwYHnvsMXTo0AF79uzBhx9+iCuvvBJ9+/YFALjdbowePRpPPPEECgsLcfvtt+Oaa65BcnIyACAtLQ2ffPIJNm3ahISEBMTExATzsgkhxAQnL4Q0IJYuXYqUlBTY7XbExcWhR48emDNnDkaPHg2r9VgI20cffYS///3vGDNmDPbv34/k5GScd955SEpKUv20a9cOV111FS655BIcOnQIl156KZ577jl1fNy4cVi5ciX69u2LoqIifP7551Wu5BBCyJnEYhiGEexBEELOHNOnT8eSJUu4zT8hpMFCtxEhhBBCGhScvBBCCCGkQcHHRoQQQghpUHDlhRBCCCENCk5eCCGEENKg4OSFEEIIIQ0KTl4IIYQQ0qDg5IUQQgghDQpOXgghhBDSoODkhRBCCCENCk5eCCGEENKg4OSFEEIIIQ2K/wcnumZWHU5nbgAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 构建Embedding层\n",
    "class TransformerEmbedding(nn.Module):\n",
    "    \"\"\"\n",
    "    Transformer Embedding层\n",
    "    继承自nn.Module\n",
    "    \"\"\"\n",
    "    def __init__(self, config):\n",
    "        \"\"\"\n",
    "        初始化函数\n",
    "        :param config: \n",
    "        \"\"\"\n",
    "        super().__init__()\n",
    "        # hyper params\n",
    "        self.vocab_size = config[\"vocab_size\"]  # 词表大小\n",
    "        self.hidden_size = config[\"d_model\"] # 词向量维度\n",
    "        self.pad_idx = config[\"pad_idx\"]         # padding token的索引\n",
    "        dropout_rate = config[\"dropout\"]         # dropout比例\n",
    "        self.max_length = config[\"max_length\"]  # 句子最大长度\n",
    "\n",
    "        # layers,设置padding_idx可以让pad的词向量全为0\n",
    "        self.word_embedding = nn.Embedding(\n",
    "            self.vocab_size, self.hidden_size, padding_idx=self.pad_idx\n",
    "        )\n",
    "        self.pos_embedding = nn.Embedding(\n",
    "            self.max_length,\n",
    "            self.hidden_size,\n",
    "            _weight=self.get_positional_encoding(\n",
    "                self.max_length, self.hidden_size\n",
    "            ),# 位置编码，权重通过get_positional_encoding函数计算得到\n",
    "        )\n",
    "        self.pos_embedding.weight.requires_grad_(False) # 不更新位置编码的权重,因为位置编码是固定不变的\n",
    "        self.dropout = nn.Dropout(dropout_rate) # 随机失活层,防止过拟合\n",
    "\n",
    "    def get_word_embedding_weights(self):\n",
    "        \"\"\"\n",
    "        获取词嵌入层的权重\n",
    "        :return:    词嵌入层的权重\n",
    "        \"\"\"\n",
    "        return self.word_embedding.weight\n",
    "\n",
    "    # 计算位置信息,位置编码\n",
    "    @classmethod\n",
    "    def get_positional_encoding(self, max_length, hidden_size):#max_length是最大长度，hidden_size是embedding维度相等\n",
    "        # Compute the positional encodings once in log space.\n",
    "        pe = torch.zeros(max_length, hidden_size) # 初始化位置编码\n",
    "        # .unsqueeze(1) 是将这个一维张量转换为二维张量，即将其形状从 (max_length,) 变为 (max_length, 1)。这个操作在张量的维度上增加了一个维度，使其从一维变为二维，第二维的大小为 1。\n",
    "        position = torch.arange(0, max_length).unsqueeze(1) # 位置信息,从0到max_length-1\n",
    "        div_term = torch.exp(\n",
    "            torch.arange(0, hidden_size, 2)\n",
    "            * -(torch.log(torch.Tensor([10000.0])) / hidden_size)\n",
    "        )# 计算位置编码的权重,为了性能考量（是数学上的对数函数分解）\n",
    "        pe[:, 0::2] = torch.sin(position * div_term)\n",
    "        pe[:, 1::2] = torch.cos(position * div_term)\n",
    "        return pe\n",
    "\n",
    "    def forward(self, input_ids):\n",
    "        # input_ids: [batch_size, seq_len]\n",
    "        seq_len = input_ids.shape[1]\n",
    "        assert (\n",
    "            seq_len <= self.max_length\n",
    "        ), f\"input sequence length should no more than {self.max_length} but got {seq_len}\"\n",
    "\n",
    "        position_ids = torch.arange(seq_len, dtype=torch.long, device=input_ids.device)\n",
    "        position_ids = position_ids.unsqueeze(0).expand_as(input_ids)\n",
    "        # print(position_ids) #为了调试\n",
    "        # embedding\n",
    "        word_embeds = self.word_embedding(input_ids) # 词嵌入\n",
    "        pos_embeds = self.pos_embedding(position_ids) # 位置编码\n",
    "        embeds = word_embeds + pos_embeds\n",
    "        embeds = self.dropout(embeds)\n",
    "\n",
    "        return embeds\n",
    "\n",
    "\n",
    "def plot_position_embedding(position_embedding):# 绘制位置编码\n",
    "    plt.pcolormesh(position_embedding) # 绘制位置编码矩阵\n",
    "    plt.xlabel('Depth')\n",
    "    plt.ylabel('Position')\n",
    "    plt.colorbar() # 颜色条，-1到1的颜色范围\n",
    "    plt.show()\n",
    "\n",
    "position_embedding = TransformerEmbedding.get_positional_encoding(64, 128)\n",
    "plot_position_embedding(position_embedding)\n",
    "# 下面的图像展示了位置编码矩阵的形状。（可视化位置编码）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "5720e0ee35ba3a4",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:03:11.484961Z",
     "start_time": "2025-03-13T11:03:11.480319Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.710173Z",
     "iopub.status.busy": "2025-03-13T12:13:39.709922Z",
     "iopub.status.idle": "2025-03-13T12:13:39.713785Z",
     "shell.execute_reply": "2025-03-13T12:13:39.713324Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.710153Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.009999999999999995\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "#为了理解指数对数变换\n",
    "def positional_encoding_weights(emb_size):\n",
    "    # 计算底数和指数\n",
    "    base = math.log(10000)\n",
    "    exponent = -5 / emb_size\n",
    "    \n",
    "    # 应用指数函数\n",
    "    weight = math.exp(exponent*base) \n",
    "    \n",
    "    return weight\n",
    "\n",
    "# 举例\n",
    "emb_size = 10 # 词嵌入维度\n",
    "weight = positional_encoding_weights(emb_size)\n",
    "print(weight)   # 输出的值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "2fb66b67d9d705a2",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:04:25.823907Z",
     "start_time": "2025-03-13T11:04:25.790286Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.714500Z",
     "iopub.status.busy": "2025-03-13T12:13:39.714322Z",
     "iopub.status.idle": "2025-03-13T12:13:39.720678Z",
     "shell.execute_reply": "2025-03-13T12:13:39.720198Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.714482Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([2, 50, 128])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#随机input，调用TransformerEmbedding\n",
    "# 下面确定config参数\n",
    "config={\n",
    "    \"vocab_size\": 100,\n",
    "    \"d_model\": 128,\n",
    "    \"pad_idx\": 0,\n",
    "    \"max_length\": 64,\n",
    "    \"dropout\": 0.1,\n",
    "}\n",
    "\n",
    "# 做个实验，看看embeds的shape\n",
    "input_ids = torch.randint(0, 100, (2, 50))\n",
    "embeds = TransformerEmbedding(config)(input_ids)\n",
    "embeds.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2e18825282ad440a",
   "metadata": {},
   "source": [
    "## 自定义Transformer Block类用于构建Transformer模型"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "437aee01dbc1b33f",
   "metadata": {},
   "source": [
    "### 点积注意力机制<br>\n",
    "点积注意力机制是最早提出的注意力机制，其计算公式如下:<br>\n",
    "$Attention(Q,K,V)=softmax(\\frac{QK^T}{\\sqrt{d_k}})V$<br>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "72b4a13acc6a1ed9",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:10:56.375731Z",
     "start_time": "2025-03-13T11:10:56.338604Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.721549Z",
     "iopub.status.busy": "2025-03-13T12:13:39.721362Z",
     "iopub.status.idle": "2025-03-13T12:13:39.734565Z",
     "shell.execute_reply": "2025-03-13T12:13:39.734040Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.721530Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "key_value.shape torch.Size([2, 4, 2])\n",
      "torch.Size([2, 3, 2])\n",
      "torch.Size([2, 2, 3, 4])\n"
     ]
    }
   ],
   "source": [
    "from dataclasses import dataclass\n",
    "from typing import Optional, Tuple\n",
    "\n",
    "Tensor = torch.Tensor\n",
    "\n",
    "@dataclass\n",
    "class AttentionOutput:\n",
    "    \"\"\"\n",
    "    AttentionOutput类用于保存注意力机制的输出\n",
    "    \"\"\"\n",
    "    hidden_states: Tensor\n",
    "    attn_scores: Tensor\n",
    "\n",
    "class MultiHeadAttention(nn.Module):\n",
    "    \"\"\"\n",
    "    多头注意力机制\n",
    "    继承自nn.Module\n",
    "    \"\"\"\n",
    "    def __init__(self, config):\n",
    "        super().__init__()\n",
    "        # hyper params\n",
    "        self.hidden_size = config[\"d_model\"] # 隐藏层大小\n",
    "        self.num_heads = config[\"num_heads\"] # 多头注意力的头数\n",
    "        assert (\n",
    "            self.hidden_size % self.num_heads == 0\n",
    "        ), \"Hidden size must be divisible by num_heads but got {} and {}\".format(\n",
    "            self.hidden_size, self.num_heads\n",
    "        )\n",
    "        self.head_dim = self.hidden_size // self.num_heads # 每个头的维度\n",
    "\n",
    "        # layers\n",
    "        self.Wq = nn.Linear(self.hidden_size, self.hidden_size, bias=False) #第二个self.hidden_size可以*系数\n",
    "        self.Wk = nn.Linear(self.hidden_size, self.hidden_size, bias=False)\n",
    "        self.Wv = nn.Linear(self.hidden_size, self.hidden_size, bias=False)\n",
    "        self.Wo = nn.Linear(self.hidden_size, self.hidden_size, bias=False) # 输出层\n",
    "\n",
    "    def _split_heads(self, x: Tensor) -> Tensor:\n",
    "        bs, seq_len, _ = x.shape #假设输入的维度是[batch_size, seq_len, hidden_size],hidden_size是512\n",
    "        x = x.view(bs, seq_len, self.num_heads, self.head_dim) #num_heads是8，head_dim是64\n",
    "        return x.permute(0, 2, 1, 3) #变换维度，[batch_size, num_heads, seq_len, head_dim]\n",
    "\n",
    "    def _merge_heads(self, x: Tensor) -> Tensor:#将多头注意力的输出合并为一个张量\n",
    "        bs, _, seq_len, _ = x.shape #假设输入的维度是[batch_size, num_heads, seq_len, head_dim]\n",
    "        return x.permute(0, 2, 1, 3).reshape(bs, seq_len, self.hidden_size) # 变换维度，变为[batch_size, seq_len, hidden_size]\n",
    "\n",
    "    def forward(self, querys, keys, values, attn_mask=None) -> AttentionOutput:\n",
    "        \"\"\"\n",
    "        多头注意力机制的前向传播\n",
    "        :param querys:  [batch_size, seq_len, hidden_size]\n",
    "        :param keys:    [batch_size, seq_len, hidden_size]\n",
    "        :param values:  [batch_size, seq_len, hidden_size]\n",
    "        :param attn_mask:   [batch_size, seq_len, seq_len]\n",
    "        :return:    AttentionOutput: [batch_size, seq_len, seq_len]\n",
    "        \"\"\"\n",
    "        # split heads\n",
    "        querys = self._split_heads(self.Wq(querys)) #(batch_size, seq_len,hidden_dim)-->[batch_size, num_heads, seq_len, head_dim]\n",
    "        keys = self._split_heads(self.Wk(keys))#[batch_size, num_heads, seq_len, head_dim]\n",
    "        values = self._split_heads(self.Wv(values))#[batch_size, num_heads, seq_len, head_dim]\n",
    "\n",
    "        # calculate attention scores\n",
    "        qk_logits = torch.matmul(querys, keys.mT) # 计算注意力分数，matmul是矩阵乘法，mT是矩阵转置,qk_logits是[batch_size, num_heads, seq_len, seq_len]\n",
    "        # print(querys.shape[-2], keys.shape[-2])  #3 4\n",
    "        if attn_mask is not None:\n",
    "            attn_mask = attn_mask[:, :, : querys.shape[-2], : keys.shape[-2]]\n",
    "            qk_logits += attn_mask * -1e9 # 给需要mask的地方设置一个负无穷\n",
    "        attn_scores = F.softmax(qk_logits / (self.head_dim**0.5), dim=-1) # 计算注意力分数\n",
    "\n",
    "        # embeds的尺寸是[batch_size, num_heads, seq_len, head_dim]\n",
    "        embeds = torch.matmul(attn_scores, values) # softmax后的结果与value相乘，得到新的表示\n",
    "        embeds = self.Wo(self._merge_heads(embeds)) # 输出层 [batch_size, seq_len, hidden_size]\n",
    "\n",
    "        return AttentionOutput(hidden_states=embeds, attn_scores=attn_scores)\n",
    "\n",
    "# 举例\n",
    "mha = MultiHeadAttention({\"num_heads\": 2, \"d_model\": 2})\n",
    "query = torch.randn(2, 3, 2) # [batch_size, seq_len, hidden_size]\n",
    "query /= query.norm(dim=-1, keepdim=True) # 归一化\n",
    "key_value = torch.randn(2, 4, 2)\n",
    "print(f'key_value.shape {key_value.shape}')\n",
    "outputs = mha(query, key_value, key_value) #最终输出shape和query的shape一样\n",
    "print(outputs.hidden_states.shape)\n",
    "print(outputs.attn_scores.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "8c9f9394a6e89879",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:13:51.876696Z",
     "start_time": "2025-03-13T11:13:51.571449Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.735254Z",
     "iopub.status.busy": "2025-03-13T12:13:39.735036Z",
     "iopub.status.idle": "2025-03-13T12:13:39.980595Z",
     "shell.execute_reply": "2025-03-13T12:13:39.979931Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.735230Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAhUAAAG6CAYAAAC/RrTYAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAmJRJREFUeJzs3XecVNX5+PHPvXfa9t53WZbeUUEQERDEgiW2RI0paGIqfhNjTPLTfBPFFGJM1ESNiSZRU/yaYtTErihiARGQXhcWWLb3MrPT7j2/PwZ2GXYWFpwC5Hm/XvOCvXvunefMnDnz3HPOvasppRRCCCGEEB+TnugAhBBCCHFqkKRCCCGEEFEhSYUQQgghokKSCiGEEEJEhSQVQgghhIgKSSqEEEIIERWSVAghhBAiKiSpEEIIIURUSFIhhBBCiKiQpELE1A033MDQoUMHVfauu+5C07Sjljv33HOZMGHCx4wsuoYOHcoNN9yQ6DDi5lje1xPBYNvWoWWbm5tjHNWpRV43AZJUiDjzeDzcddddLFu2LNGhnNB++tOf8txzz/Xb/v7773PXXXfR3t4e8xhqa2u56667WLduXcyfKxEGeo0TacuWLdx1113s2bMn0aEIcVwkqRBx5fF4WLx4ccSk4n//93/p6emJf1AnoCMlFYsXL45bUrF48eKIScVjjz3G9u3bYx5DtERqWydqUrF48WJJKsRJy5boAIQ4yGazYbNJkzwZ2O32RIdwTKRtCREfMlLxX+jg3OeOHTv47Gc/S0ZGBnl5efzgBz9AKUV1dTWXX3456enpFBYW8stf/jJs/yeeeAJN0/qdTS1btgxN0wac2tizZw95eXkALF68GE3T0DSNu+66KyyuwdqyZQtz584lOTmZkpISfv7zn/cr4/P5uPPOOxkxYgROp5OysjK++93v4vP5wso9/vjjzJs3j/z8fJxOJ+PGjeORRx7pdzylFD/+8Y8pLS0lOTmZuXPnsnnz5kHH/Itf/IKzzz6bnJwckpKSmDJlCv/85z/Dymiahtvt5sknn+x9jW644QbuuusuvvOd7wBQUVHR+7tD34e//OUvTJkyhaSkJLKzs7nuuuuorq4OO/7BNSlHev2WLVvGmWeeCcCNN97Y+1xPPPEEEHlNhdvt5tvf/jZlZWU4nU5Gjx7NL37xCw7/Q8iapnHzzTfz3HPPMWHCBJxOJ+PHj+eVV1454munlCI3N5dbb721d5tlWWRmZmIYRtjozT333IPNZqO7uxvo37YGeo0P1d7ezg033EBmZiYZGRnceOONeDyesDLBYJAf/ehHDB8+HKfTydChQ7njjjv6ta9D2/mhDl2L88QTT/CpT30KgLlz5/bGdaSpwhtuuIHU1FT27dvHpZdeSmpqKiUlJTz88MMAbNy4kXnz5pGSkkJ5eTlPPfVU2P6tra3cdtttTJw4kdTUVNLT01mwYAHr16/v91wPPvgg48ePJzk5maysLKZOndrveIfbu3cvI0aMYMKECTQ0NByxrDg1SFLxX+zaa6/Fsix+9rOfMX36dH784x/zwAMPcP7551NSUsI999zDiBEjuO2221i+fPnHfr68vLzeL+orr7ySP//5z/z5z3/mqquuOuZjtbW1cdFFFzF58mR++ctfMmbMGL73ve/x8ssv95axLItPfOIT/OIXv+Cyyy7jwQcf5IorruD+++/n2muvDTveI488Qnl5OXfccQe//OUvKSsr4+tf/3pv53zQD3/4Q37wgx8wefJk7r33XoYNG8YFF1yA2+0eVNy/+tWvOP3007n77rv56U9/is1m41Of+hQvvvhib5k///nPOJ1OZs2a1fsafeUrX+Gqq67i05/+NAD3339/7+8OJmo/+clP+PznP8/IkSO57777uOWWW1i6dCmzZ8/uN11ytNdv7Nix3H333QB8+ctf7n2u2bNnR6yXUopPfOIT3H///Vx00UXcd999jB49mu985zthScBB7777Ll//+te57rrr+PnPf47X6+Xqq6+mpaVlwNdO0zRmzpwZ1hY3bNhAR0cHAO+9917v9nfeeYfTTz+d1NTUiMca6DU+1DXXXENXVxdLlizhmmuu4YknnmDx4sVhZW666SZ++MMfcsYZZ3D//fczZ84clixZwnXXXTdgPQYye/ZsvvGNbwBwxx139MY1duzYI+5nmiYLFiygrKyMn//85wwdOpSbb76ZJ554gosuuoipU6dyzz33kJaWxuc//3mqqqp69929ezfPPfccl156Kffddx/f+c532LhxI3PmzKG2tra33GOPPcY3vvENxo0bxwMPPMDixYs57bTT+OCDDwaMa9euXcyePZu0tDSWLVtGQUHBMb8m4iSkxH+dO++8UwHqy1/+cu+2YDCoSktLlaZp6mc/+1nv9ra2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",
      "text/plain": [
       "<Figure size 640x480 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# plt.subplots() 用于创建子图网格，其维度基于 outputs.attn_scores.shape[:2]。子图的行数和列数似乎由 outputs.attn_scores 的前两个维度确定。\n",
    "\n",
    "# 绘制注意力矩阵\n",
    "# 这里的数据是随机生成的，只是看看效果\n",
    "fig, axis = plt.subplots(*outputs.attn_scores.shape[:2])\n",
    "for i in range(query.shape[0]):\n",
    "    for j in range(outputs.attn_scores.shape[1]):\n",
    "        # axis[i, j].matshow(outputs.attn_scores[i, j].detach().numpy())：此行使用 Matplotlib 的 matshow 绘制每个 i 和 j 的注意力分数热图。detach().numpy() 将 PyTorch 张量转换为 NumPy 数组以进行可视化。\n",
    "        axis[i, j].matshow(outputs.attn_scores[i, j].detach().numpy(),cmap='coolwarm')\n",
    "        for x in range(outputs.attn_scores.shape[2]):\n",
    "            for y in range(outputs.attn_scores.shape[3]):\n",
    "                # axis[i, j].text(y, x, f\"{outputs.attn_scores[i, j, x, y]:.2f}\", ha=\"center\", va=\"center\", color=\"w\")：此代码在热图上叠加文本，显示 (x, y) 位置处的注意力分数。格式化部分 f\"{outputs.attn_scores[i, j, x, y]:.2f}\" 确保以两位小数显示注意力分数。文本以白色居中显示在 (y, x) 坐标处。\n",
    "                axis[i, j].text(y, x, f\"{outputs.attn_scores[i, j, x, y]:.2f}\", ha=\"center\", va=\"center\", color=\"w\")\n",
    "fig.suptitle(\"multi head attention without mask\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "13f75373f7adee6f",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:14:50.491009Z",
     "start_time": "2025-03-13T11:14:50.278978Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:39.981382Z",
     "iopub.status.busy": "2025-03-13T12:13:39.981198Z",
     "iopub.status.idle": "2025-03-13T12:13:40.299286Z",
     "shell.execute_reply": "2025-03-13T12:13:40.298582Z",
     "shell.execute_reply.started": "2025-03-13T12:13:39.981362Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------------------------------------------------\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAhUAAAG6CAYAAAC/RrTYAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAgjhJREFUeJzt3XeYG9W5P/DvFPVVXW0v9rp3AwYbB2zAGAjFBEgoN+HGOJeUGzs3hJT7I+ViE4ghECAQCLkpkOSGBJLQQkIoDtgGbDA2xnVdd+3tTVp1jaac3x9aa1e7WnvXHkle8X6eRw/s6MzoPdLo1Ttnzow5xhgDIYQQQsgp4vMdACGEEEIKAxUVhBBCCNEFFRWEEEII0QUVFYQQQgjRBRUVhBBCCNEFFRWEEEII0QUVFYQQQgjRBRUVhBBCCNEFFRWEEEII0QUVFeS0dMstt2D8+PEjart69WpwHHfCdhdeeCFmzZp1ipHpa/z48bjlllvyHUbOjOZzPR2MdN8a2La7uzvLUWXfLbfcgqKionyHQcYgKirImBCNRrF69Wq89dZb+Q7ltPajH/0IL7zwwpDl7777LlavXo3e3t6sx9Da2orVq1dj+/btWX+tfBjuPSaEUFFBxohoNIo1a9ZkLCq+//3vIxaL5T6o09Dxioo1a9bkrKhYs2ZNxqLil7/8Jfbt25f1GPSSad+iooKQ4Yn5DoCQUyWKIkSRduWxwGAw5DuEUaF9i5DRoZEKMmLHzhnv378fN998M5xOJ0pKSvCDH/wAjDE0NTXhU5/6FBwOB8rLy/GTn/wkbf2nnnoKHMehsbExbflbb70FjuOGPbXR2NiIkpISAMCaNWvAcRw4jsPq1avT4hqpPXv24KKLLoLVakVVVRV+/OMfD2kjSRLuvPNOTJo0CSaTCTU1NfjOd74DSZLS2j355JNYsmQJSktLYTKZMGPGDPz85z8fsj3GGO6++25UV1fDarXioosuwu7du0cc8wMPPIBPfOITKC4uhsViwbx58/CXv/wlrQ3HcYhEIvjtb3+beo9uueUWrF69Gt/+9rcBAHV1dannBn4O//d//4d58+bBYrHA4/HgpptuQlNTU9r2j81JOd7799Zbb+Gcc84BAKxYsSL1Wk899RSAzHMqIpEIvvnNb6KmpgYmkwlTp07FAw88gMH/gDLHcVi1ahVeeOEFzJo1CyaTCTNnzsQ///nP4753jDF4vV7cfvvtqWWapsHlckEQhLTRm/vuuw+iKCIcDgMYum8N9x4P1Nvbi1tuuQUulwtOpxMrVqxANBo9boxA//u7Y8cOXHDBBbBarZg0aVLqc16/fj0WLFgAi8WCqVOn4o033khb/8iRI/jqV7+KqVOnwmKxoLi4GNdff/2Q75ssy1izZg0mT54Ms9mM4uJinH/++Xj99dePG9/27dtRUlKCCy+8MPX+EDIYFRVk1G688UZomoZ7770XCxYswN13342HH34Yl1xyCaqqqnDfffdh0qRJ+Na3voUNGzac8uuVlJSkfqivvfZa/P73v8fvf/97XHfddaPelt/vxyc/+UnMnTsXP/nJTzBt2jT893//N1555ZVUG03TcPXVV+OBBx7AsmXL8Oijj+Kaa67BQw89hBtvvDFtez//+c8xbtw4fPe738VPfvIT1NTU4Ktf/Soee+yxtHb/8z//gx/84AeYO3cu7r//fkyYMAGXXnopIpHIiOL+6U9/ijPPPBN33XUXfvSjH0EURVx//fX4+9//nmrz+9//HiaTCYsWLUq9R1/+8pdx3XXX4d/+7d8AAA899FDquWOF2j333IPPf/7zmDx5Mh588EHcdtttWLduHRYvXjzkdMmJ3r/p06fjrrvuAgB86UtfSr3W4sWLM/aLMYarr74aDz30ED75yU/iwQcfxNSpU/Htb387rQg45u2338ZXv/pV3HTTTfjxj3+MeDyOT3/60+jp6Rn2veM4Duedd17avrhjxw4EAgEAwDvvvJNavnHjRpx55pnDTlIc7j0e6IYbbkAoFMLatWtxww034KmnnsKaNWuGjW8gv9+Pq666CgsWLMCPf/xjmEwm3HTTTXjmmWdw00034YorrsC9996LSCSCz3zmMwiFQql1t2zZgnfffRc33XQTHnnkEXzlK1/BunXrcOGFF6YVNatXr8aaNWtw0UUX4Wc/+xm+973voba2Ftu2bRs2ri1btmDJkiU488wz8corr9AkTjI8RsgI3XnnnQwA+9KXvpRapigKq66uZhzHsXvvvTe13O/3M4vFwpYvX55a9uSTTzIArKGhIW27b775JgPA3nzzzdSy5cuXs3HjxqX+7urqYgDYnXfeOWxcJ3LBBRcwAOx3v/tdapkkSay8vJx9+tOfTi37/e9/z3ieZxs3bkxb/4knnmAA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",
      "text/plain": [
       "<Figure size 640x480 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 相比于上面的图象，下面这个图象展示了mask的效果\n",
    "print('-'*50)\n",
    "# mask\n",
    "mask = torch.Tensor([[0, 0, 1, 1], [0, 0, 0, 1], [0, 0, 0, 0]]).reshape(1, 1, 3, 4) #手工构造mask\n",
    "outputs_masked = mha(query, key_value, key_value, mask)\n",
    "\n",
    "fig, axis = plt.subplots(*outputs_masked.attn_scores.shape[:2])\n",
    "for i in range(query.shape[0]):\n",
    "    for j in range(outputs_masked.attn_scores.shape[1]):\n",
    "        axis[i, j].matshow(outputs_masked.attn_scores[i, j].detach().numpy(),cmap='coolwarm')\n",
    "        for x in range(outputs_masked.attn_scores.shape[2]):\n",
    "            for y in range(outputs_masked.attn_scores.shape[3]):\n",
    "                axis[i, j].text(y, x, f\"{outputs_masked.attn_scores[i, j, x, y]:.2f}\", ha=\"center\", va=\"center\", color=\"w\")\n",
    "fig.suptitle(\"multi head attention with mask\")\n",
    "plt.show()\n",
    "\n",
    "#注意到mask的作用，在mask的地方，注意力分数为0，使得模型不关注mask的位置。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea21d1d69faf08bb",
   "metadata": {},
   "source": [
    "### Transformer Block<br>\n",
    "Transformer Block是Transformer模型的基本组成单元，由多头注意力机制、前馈网络、残差连接和LayerNorm等层组成。<br>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "fa421e48971e903a",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:15:46.175876Z",
     "start_time": "2025-03-13T11:15:46.167528Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:40.300450Z",
     "iopub.status.busy": "2025-03-13T12:13:40.300092Z",
     "iopub.status.idle": "2025-03-13T12:13:40.313222Z",
     "shell.execute_reply": "2025-03-13T12:13:40.312752Z",
     "shell.execute_reply.started": "2025-03-13T12:13:40.300413Z"
    }
   },
   "outputs": [],
   "source": [
    "# 通过使用 @dataclass 装饰器，Python 会自动为该类生成一些方法，如 __init__()、__repr__() 和 __eq__() 等，这些方法可以使类的使用更加方便。\n",
    "@dataclass\n",
    "class TransformerBlockOutput:\n",
    "# hidden_states: Tensor：用于存储某个块产生的隐藏状态。\n",
    "# self_attn_scores: Tensor：包含了自注意力机制（self-attention）所计算得到的注意力分数。\n",
    "# cross_attn_scores: Optional[Tensor] = None：是一个可选字段，存储了交叉注意力（cross-attention）计算得到的注意力分数。这里的 Optional 表示这个字段可以是 Tensor 类型，也可以是 None。\n",
    "    hidden_states: Tensor\n",
    "    self_attn_scores: Tensor\n",
    "    cross_attn_scores: Optional[Tensor] = None\n",
    "\n",
    "class TransformerBlock(nn.Module):\n",
    "    def __init__(self, config, add_cross_attention=False):\n",
    "        super().__init__()\n",
    "        # hyper params\n",
    "        self.hidden_size = config[\"d_model\"]\n",
    "        self.num_heads = config[\"num_heads\"]\n",
    "        dropout_rate = config[\"dropout\"]\n",
    "        ffn_dim = config[\"dim_feedforward\"]\n",
    "        eps = config[\"layer_norm_eps\"] # 层归一化的epsilon值\n",
    "\n",
    "        # self-attention\n",
    "        self.self_atten = MultiHeadAttention(config) # 多头注意力\n",
    "        self.self_ln = nn.LayerNorm(self.hidden_size, eps=eps) #层归一化(层标准化)\n",
    "        self.self_dropout = nn.Dropout(dropout_rate)\n",
    "\n",
    "        # cross-attention，交叉注意力，decoder中使用,因此额外做一个判断\n",
    "        if add_cross_attention:\n",
    "            self.cross_atten = MultiHeadAttention(config)\n",
    "            self.cross_ln = nn.LayerNorm(self.hidden_size, eps=eps)\n",
    "            self.cross_dropout = nn.Dropout(dropout_rate)\n",
    "        else:\n",
    "            self.cross_atten = None\n",
    "\n",
    "        # FFN,前馈神经网络\n",
    "        self.ffn = nn.Sequential(\n",
    "            nn.Linear(self.hidden_size, ffn_dim),\n",
    "            nn.ReLU(),\n",
    "            nn.Linear(ffn_dim, self.hidden_size),\n",
    "        )\n",
    "        self.ffn_ln = nn.LayerNorm(self.hidden_size, eps=eps)\n",
    "        self.ffn_dropout = nn.Dropout(dropout_rate)\n",
    "\n",
    "    def forward(\n",
    "        self,\n",
    "        hidden_states,\n",
    "        attn_mask=None,\n",
    "        encoder_outputs=None,\n",
    "        cross_attn_mask=None,\n",
    "    ):\n",
    "        # self-attention,自注意力\n",
    "        self_atten_output = self.self_atten(\n",
    "            hidden_states, hidden_states, hidden_states, attn_mask\n",
    "        )\n",
    "        self_embeds = self.self_ln(\n",
    "            hidden_states + self.self_dropout(self_atten_output.hidden_states)\n",
    "        ) #多头注意力进行dropout，然后和原始输入进行残差连接，然后进行层归一化\n",
    "\n",
    "        # cross-attention，交叉注意力\n",
    "        if self.cross_atten is not None:\n",
    "            assert encoder_outputs is not None\n",
    "            cross_atten_output = self.cross_atten(\n",
    "                self_embeds, encoder_outputs, encoder_outputs, cross_attn_mask\n",
    "            ) #query是self_embeds，key和value都是encoder_outputs\n",
    "            cross_embeds = self.cross_ln(\n",
    "                self_embeds + self.cross_dropout(cross_atten_output.hidden_states)\n",
    "            ) # 交叉注意力进行dropout，然后和self_embeds进行残差连接，然后进行层归一化\n",
    "\n",
    "        # FFN\n",
    "        embeds = cross_embeds if self.cross_atten is not None else self_embeds # 如果有交叉注意力，则使用交叉注意力的输出作为FFN的输入；否则，使用self_embeds作为FFN的输入\n",
    "        ffn_output = self.ffn(embeds) # 前馈神经网络\n",
    "        embeds = self.ffn_ln(embeds + self.ffn_dropout(ffn_output)) # 前馈神经网络进行dropout，然后和原始输入进行残差连接，然后进行层归一化\n",
    "\n",
    "        return TransformerBlockOutput(\n",
    "            hidden_states=embeds,\n",
    "            self_attn_scores=self_atten_output.attn_scores,\n",
    "            cross_attn_scores=cross_atten_output.attn_scores\n",
    "            if self.cross_atten is not None\n",
    "            else None,\n",
    "        )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9ad925f66dfb3cd1",
   "metadata": {},
   "source": [
    "### Encoder<br>\n",
    "Encoder是Transformer模型的核心组件之一，用于对输入序列进行编码，输出编码后的序列表示。并返回处理后的hiddens状态和注意力分数。<br>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "a841505ddee279a1",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:16:52.932326Z",
     "start_time": "2025-03-13T11:16:52.926149Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:40.314012Z",
     "iopub.status.busy": "2025-03-13T12:13:40.313837Z",
     "iopub.status.idle": "2025-03-13T12:13:40.319515Z",
     "shell.execute_reply": "2025-03-13T12:13:40.319072Z",
     "shell.execute_reply.started": "2025-03-13T12:13:40.313992Z"
    }
   },
   "outputs": [],
   "source": [
    "from typing import List\n",
    "\n",
    "@dataclass\n",
    "class TransformerEncoderOutput:\n",
    "    last_hidden_states: Tensor\n",
    "    attn_scores: List[Tensor]\n",
    "\n",
    "# https://pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module\n",
    "class TransformerEncoder(nn.Module):\n",
    "    def __init__(self, config):\n",
    "        super().__init__()\n",
    "        # hyper params\n",
    "        self.num_layers = config[\"num_encoder_layers\"]\n",
    "\n",
    "        # layers,仅仅是一个模块的列表，它本身没有定义前向传递（forward pass）过程。你需要在 forward 方法中明确地定义如何使用这些模块。\n",
    "        self.layers = nn.ModuleList(\n",
    "            [TransformerBlock(config) for _ in range(self.num_layers)]\n",
    "        )\n",
    "\n",
    "    def forward(\n",
    "        self, encoder_inputs_embeds, attn_mask=None\n",
    "    ) -> TransformerEncoderOutput:\n",
    "        attn_scores = [] # 存储每个层的注意力分数\n",
    "        embeds = encoder_inputs_embeds # 输入的嵌入向量作为第一层的输入(embedding+位置编码)\n",
    "        for layer in self.layers:\n",
    "            block_outputs = layer(embeds, attn_mask=attn_mask)\n",
    "            embeds = block_outputs.hidden_states #上一层的输出作为下一层的输入\n",
    "            # 在每个层的输出中，提取了隐藏状态 block_outputs.hidden_states，并将对应的注意力分数 block_outputs.self_attn_scores 添加到列表 attn_scores 中。\n",
    "            attn_scores.append(block_outputs.self_attn_scores) # 存储每个层的注意力分数,用于画图\n",
    "\n",
    "        return TransformerEncoderOutput(\n",
    "            last_hidden_states=embeds, attn_scores=attn_scores\n",
    "        )   # 返回编码后的序列表示和注意力分数\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15f036521d88205",
   "metadata": {},
   "source": [
    "### Decoder<br>\n",
    "Decoder是Transformer模型的核心组件之一，用于对输入序列进行解码<br>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "74721a8f8679a33f",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:34:52.778423Z",
     "start_time": "2025-03-13T11:34:52.773176Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:40.323050Z",
     "iopub.status.busy": "2025-03-13T12:13:40.322743Z",
     "iopub.status.idle": "2025-03-13T12:13:40.328717Z",
     "shell.execute_reply": "2025-03-13T12:13:40.328253Z",
     "shell.execute_reply.started": "2025-03-13T12:13:40.323029Z"
    }
   },
   "outputs": [],
   "source": [
    "@dataclass\n",
    "class TransformerDecoderOutput:\n",
    "    last_hidden_states: Tensor\n",
    "    self_attn_scores: List[Tensor]\n",
    "    cross_attn_scores: List[Tensor]\n",
    "\n",
    "\n",
    "class TransformerDecoder(nn.Module):\n",
    "    def __init__(self, config):\n",
    "        super().__init__()\n",
    "        # hyper params\n",
    "        self.num_layers = config[\"num_decoder_layers\"]\n",
    "\n",
    "        # layers\n",
    "        self.layers = nn.ModuleList(\n",
    "            [\n",
    "                TransformerBlock(config, add_cross_attention=True)\n",
    "                for _ in range(self.num_layers)\n",
    "            ]\n",
    "        )\n",
    "\n",
    "    def forward(\n",
    "        self,\n",
    "        decoder_inputs_embeds,\n",
    "        encoder_outputs,\n",
    "        attn_mask=None,\n",
    "        cross_attn_mask=None,\n",
    "    ) -> TransformerDecoderOutput:\n",
    "        self_attn_scores = [] # 存储每个层的自注意力分数\n",
    "        cross_attn_scores = [] # 存储每个层的交叉注意力分数\n",
    "        embeds = decoder_inputs_embeds # 输入的嵌入向量作为第一层的输入(embedding+位置编码)\n",
    "        for layer in self.layers:\n",
    "            block_outputs = layer(\n",
    "                embeds,\n",
    "                attn_mask=attn_mask, # 自注意力的mask\n",
    "                encoder_outputs=encoder_outputs,\n",
    "                cross_attn_mask=cross_attn_mask, # 交叉注意力的mask\n",
    "            )\n",
    "            embeds = block_outputs.hidden_states # 上一层的输出作为下一层的输入\n",
    "            self_attn_scores.append(block_outputs.self_attn_scores) # 存储每个层的自注意力分数,为了画图\n",
    "            cross_attn_scores.append(block_outputs.cross_attn_scores) # 存储每个层的交叉注意力分数，为了画图\n",
    "\n",
    "        return TransformerDecoderOutput(\n",
    "            last_hidden_states=embeds,\n",
    "            self_attn_scores=self_attn_scores,\n",
    "            cross_attn_scores=cross_attn_scores,\n",
    "        )\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "45ef3325e9bb34e",
   "metadata": {},
   "source": [
    "### Mask<br>\n",
    "在Transformer模型中，mask的作用是使得模型不关注mask的位置，从而提高模型的性能。<br>\n",
    "\n",
    "\n",
    "- mask实际上大类上只有两种\n",
    "    1. `padding_mask`：mask掉`pad_idx`，不计算损失\n",
    "    2. `attention_mask`：mask掉`pad_idx`，不计算注意力分数\n",
    "- Decoder的`attention_mask`和Encoder有一定的区别：\n",
    "    - Encoder可以同时看见序列所有信息，故只mask掉`pad_idx`\n",
    "    - Decoder只能看到在自身之前的序列的信息，故要额外mask掉自身之后的序列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "2c1e95cefc560e61",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:18:30.235401Z",
     "start_time": "2025-03-13T11:18:30.107943Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:40.329419Z",
     "iopub.status.busy": "2025-03-13T12:13:40.329244Z",
     "iopub.status.idle": "2025-03-13T12:13:40.476537Z",
     "shell.execute_reply": "2025-03-13T12:13:40.476013Z",
     "shell.execute_reply.started": "2025-03-13T12:13:40.329400Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 480x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 构造一个mask，这里展示的是look-ahead mask，即自注意力的mask,避免模型看到未来信息\n",
    "def generate_square_subsequent_mask(sz: int) -> Tensor:\n",
    "    \"\"\"\n",
    "    Generate a square mask for the sequence. The masked positions are filled with True.\n",
    "        Unmasked positions are filled with False.\n",
    "    \"\"\"\n",
    "    # torch.ones(sz, sz): 创建一个全为 1 的 sz × sz 的矩阵。\n",
    "    # torch.triu(...): 使用 triu 函数取得矩阵的上三角部分，将主对角线以下部分置零。\n",
    "    mask = (torch.triu(torch.ones(sz, sz)) == 0).transpose(-1, -2).bool()\n",
    "    # mask = torch.triu(torch.ones(sz, sz))\n",
    "    return mask\n",
    "\n",
    "# 测试生成的mask\n",
    "plt.matshow(generate_square_subsequent_mask(16),cmap='coolwarm') #画出一个16×16的矩阵热力图，黄色部分为True，是掩码\n",
    "plt.colorbar()\n",
    "plt.xlabel(\"keys\")\n",
    "plt.ylabel(\"querys\")\n",
    "plt.title(\"1 means mask while 0 means unmask\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "fa6e7d02fce68831",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:19:58.459713Z",
     "start_time": "2025-03-13T11:19:58.034963Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:40.477196Z",
     "iopub.status.busy": "2025-03-13T12:13:40.477014Z",
     "iopub.status.idle": "2025-03-13T12:13:40.956648Z",
     "shell.execute_reply": "2025-03-13T12:13:40.956127Z",
     "shell.execute_reply.started": "2025-03-13T12:13:40.477177Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['[BOS]', '[UNK]', 'quick', 'brown', '[UNK]', 'jumps', 'over', 'the', '[UNK]', 'dog', '.', '[EOS]']\n"
     ]
    },
    {
     "data": {
      "image/png": "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P//5z5o4caJeeOEF3XTTTXJxcdGMGTPs9rNjx446dOiQPvvsM3355Zf65z//qbffflvPPfec5s2bZzf+b37zG73//vuKi4vT73//e1P7AgC1mYeHh+677z6tW7dOX375pe6//37TYzzxxBNatmyZZsyYobvvvltWq1UWi0WjR48us/+U91pfcp+VK1eqRYsWpbZzc/vf/1o6oveVhT4GRyFIoU665ZZb9Pjjj+vxxx/XTz/9pB49euill17Sa6+9Jkny8fHRwIEDHVLL+fPnlZiYqHnz5um5556zrS95V+9K1/sG99rw7e7/+Mc/1L9/f7377rt26y9cuFDqQ7VeXl6KjIxUZGSk8vPz9eCDD+qll15SdHS03SkvCxculJubmx5//HE1btz4mh/iBQBnuf322yVJhw4dUtu2bW3r8/Pzdfz4cVu/uXK7e++9126MQ4cO2W4vYbFYFBcXp+HDh2vkyJGKj49XWFiYqdr+8Y9/aPz48Vq0aJFtXW5ubplXE6yIkgsdNWvW7Lp9tKK9z8/PT56enmX2xEOHDlWqxhtBH4MZnNqHOqWoqKjUqQrNmjVTy5YtlZeXp8DAQLVr106vvPJKmZeOLesSrzeq5B2wq48Mvf7666W29fLykqQyG5yXl1elG5+juLq6ltrPv//976Uu63v1pW8bNGigTp06yTAMFRQU2N1msVgUGxur3/72txo/frw+/fTT6ikeACpp4MCBatCggd544w2718B3331XWVlZGjp0qCSpZ8+eatasmZYsWaK8vDzbdvHx8Tpw4IBtuys1aNBAa9euVVBQkIYNG6aUlBRTtZX1uvzmm2+qqKjI1DglwsPD5ePjo/nz55d6vZb+10cr2vtcXV0VHh6uTz75RD/88INt/YEDB7R+/fpK1Xgj6GMwgyNSqFNycnLUqlUr/fa3v9Vdd90lb29vbdy4Ubt27dKiRYvk4uKipUuXKiIiQp07d9aECRN066236uTJk9q0aZN8fHz0r3/9q0pr8vHxsV2CtaCgQLfeeqsSEhJ0/PjxUtsGBgZKkmbPnq3Ro0fL3d1dw4YNk5eXlwIDA7Vx40a9+uqratmypdq0aaPevXtXaa036v7779fzzz+vCRMm6J577lFqaqri4uLs3qGVpMGDB6tFixbq27evmjdvrgMHDuitt97S0KFD1bhx41Ljuri46IMPPtCIESM0atQoffHFF6XezQUAZ/Hz81N0dLTmzZunIUOG6Ne//rUOHTqkt99+W0FBQRo7dqwkyd3dXQsWLNCECRMUGhqqhx56yHb589atW+vJJ58sc3xPT0999tlnuvfeexUREaHNmzfrzjvvrFBt999/v1auXCmr1apOnTppx44d2rhxo5o2bVqpffXx8dHixYv1yCOPqEePHho9erT8/Pz0ww8/6PPPP1ffvn311ltvmep98+bN05dffqng4GA9/vjjKiwstH1H0/79+ytVZ2XRx2CKcy4WCFSPvLw846mnnjLuuusuo3HjxoaXl5dx1113GW+//bbddnv27DEefPBBo2nTpoaHh4dx++23G6NGjTISExNt21Tl5c8zMjKMBx54wPD19TWsVqsxcuRIIzMzs9RlVw3DMF544QXj1ltvNVxcXOzmP3jwoBESEmJ4enoakmyXQr/y8qpXKqv+8lxr/0JDQ8u8zOvtt99uDB061PZ7bm6uMXPmTOOWW24xPD09jb59+xo7duwwQkNDjdDQUNt277zzjhESEmJ7/Nu1a2c89dRTRlZWlm2bsvbr8uXLRmhoqOHt7W3s3LmzwvsFAFWtrNfYt956y7jjjjsMd3d3o3nz5saUKVOM8+fPl7rv6tWrje7duxseHh7GTTfdZDz88MNGRkaG3TZlvR6fOXPG6NSpk9GiRQvj8OHDFarz/PnzxoQJE4ybb77Z8Pb2NsLDw42DBw8at99+u91XapTsz65du+zuv2nTJkOSsWnTplLrw8PDDavVajRs2NBo166dERUVZezevdu2jZnet3nzZiMwMNBo0KCB0bZtW2PJkiW2PmAGfQyOZDEMk59EBwAAAIB6js9IAQAAAIBJfEYKuAFZWVn6+eefr7tNWZeHdbTaUicAoGIuXrxY5kWTruTn53fNS37XNvQx1ESc2gfcgKioKL3//vvX3aYmPMVqS50AgIqZO3duqe8rutrx48fVunVrxxRUzehjqIkIUsAN+P7775WZmXndbRz1fVXXU1vqBABUzLFjx3Ts2LHrbtOvXz+77zOqzehjqIkIUgAAAABgEhebAAAAAACTCFIAAAAAYBJBChWyfPly7dixo8zb5s6dq88++6xC4yQlJWnWrFlVWVqNtXfvXi1evNjZZTjNiRMnlJCQIEnq2bOnk6txjG+//VZRUVHOLgOoN+hN5tGb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",
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------------------------------------------------\n",
      "['[BOS]', '[UNK]', 'does', 'the', '[UNK]', 'say', '?', '[EOS]', '[PAD]', '[PAD]', '[PAD]', '[PAD]']\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1AAAAG1CAYAAAD3DRUpAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAARzZJREFUeJzt3XtcVHX+x/E3iA4IMlihRlCpmWaZFt5+KoKYCFlrmYqXVlE3N7XCUkseXbyVZGTaXVlLu1jmhWo3l8QbXlLTNhPd1LVSA9HSVDAV5HJ+f+yDWSYQDzjODPB6Ph7zWOfMme/nc1idT2/OzBkPwzAMAQAAAAAuydPVDQAAAABAdUGAAgAAAACTCFAAAAAAYBIBCgAAAABMIkABAAAAgEkEKAAAAAAwiQAFAAAAACYRoAAAAADAJAIUAAAAAJhEgALKsWjRInl4eOjQoUN225OSktSsWTPVqVNH7dq1c0lvtcHUqVPl4eGhEydOuLoVACjjYjPCUeLi4uTn53dF1i5PyfF88803Tqt5KSVzoLpijtVsBCjApLS0ND355JPq2rWrFi5cqJkzZzp0/S1btmjq1Kk6ffp0mcdmzpypzz77zKH1AAAAUHkEKMCkdevWydPTU++8846GDRumu+++26Hrb9myRdOmTSNAAQAAuDECFGDSr7/+Kh8fH9WrV8/VrQAAAMBFCFCoUc6cOaPx48frxhtvlMViUaNGjdSrVy99++23tn2+/vprRUdHy2q1qn79+goPD9dXX31V4boeHh5auHChzp49Kw8PD3l4eGjRokWmesrIyFBcXJyaNWsmb29vNWnSRCNHjtRvv/1m22fq1KmaNGmSJKlp06a2GocOHZKHh4fOnj2r9957z7Y9Li7O9jwPDw/98MMPiouLU0BAgKxWq0aMGKFz585V6mdX8p77n3/+Wffcc4/8/Px03XXX6c0335Qk7d69W5GRkfL19dUNN9ygjz76yO75J0+e1MSJE9WmTRv5+fnJ399fMTEx2rVrV5lar7/+um699VbVr19fDRs2VPv27cus90eHDx/WTTfdpNtuu02//PJLpY4NAK60t956S7feeqssFouCgoI0bty4ct9RsGzZMoWGhsrHx0fXXHONHnzwQR05cuSS63/33XcKDAxURESEfv/9d1M9HT58WGPHjlXLli3l4+Ojq6++WgMGDLjoZ7fy8/P1xBNPKDAwUL6+vrr//vt1/PjxMvulpqYqLCxMvr6+atCggfr06aN///vfdvuYmX0lNm/erA4dOsjb21vNmzfX/PnzTR3fHzHH4Cxerm4AcKSHH35Yy5cv1yOPPKLWrVvrt99+0+bNm7V3717deeedWrdunWJiYhQaGqopU6bI09NTCxcuVGRkpDZt2qSOHTuWu+4HH3yg5ORkbd++XQsWLJAkdenSxVRPq1ev1k8//aQRI0aoSZMm+ve//63k5GT9+9//1rZt2+Th4aF+/frpP//5jz7++GPNmTNH11xzjSQpMDBQH3zwgf7yl7+oY8eOGj16tCSpefPmdjUGDhyopk2bKjExUd9++60WLFigRo0aadasWZX6+RUVFSkmJkbdu3fXSy+9pMWLF+uRRx6Rr6+vnn76aQ0dOlT9+vXTvHnzNGzYMP3f//2fmjZtKkn66aef9Nlnn2nAgAFq2rSpfvnlF82fP1/h4eH6/vvvFRQUJEn629/+pscee0z9+/dXfHy88vLylJGRoa+//lpDhgwpt68ff/xRkZGRuuqqq7R69WrbzwcA3MHUqVM1bdo03XXXXRozZoz279+vt99+Wzt27NBXX32lunXrSvrvxRpGjBihDh06KDExUb/88oteffVVffXVV9q5c6cCAgLKXX/Hjh3q3bu32rdvr88//1w+Pj6m+tqxY4e2bNmiQYMGKTg4WIcOHdLbb7+tiIgIff/996pfv77d/o8++qgaNmyoKVOm6NChQ5o7d64eeeQRffLJJ7Z9PvjgAw0fPly9e/fWrFmzdO7cOb399tvq1q2bdu7cqRtvvFGSudkn/TfUREVFKTAwUFOnTlVhYaGmTJmixo0bV/L/hf9ijsEpDKAGsVqtxrhx48p9rLi42GjRooXRu3dvo7i42Lb93LlzRtOmTY1evXrZti1cuNCQZBw8eNC2bfjw4Yavr2+lezp37lyZbR9//LEhydi4caNtW1JSUpmaJXx9fY3hw4eX2T5lyhRDkjFy5Ei77ffff79x9dVXV6rP4cOHG5KMmTNn2radOnXK8PHxMTw8PIwlS5bYtu/bt8+QZEyZMsW2LS8vzygqKrJb8+DBg4bFYjGmT59u29a3b1/j1ltvrbCXkuM6fvy4sXfvXiMoKMjo0KGDcfLkyUodEwBcCaVnxK+//mrUq1fPiIqKsnsNfOONNwxJxrvvvmsYhmFcuHDBaNSokXHbbbcZ58+ft+33xRdfGJKM5557zrat9LzZvHmz4e/vb/Tp08fIy8urVJ/lzZ+tW7cakoz333+/zPHcdddddvPx8ccfN+rUqWOcPn3aMAzDOHPmjBEQEGA89NBDdmseO3bMsFqtdtvNzr777rvP8Pb2Ng4fPmzb9v333xt16tQxKvufqcwxOAtv4UONEhAQoK+//lrZ2dllHvvuu+904MABDRkyRL/99ptOnDihEydO6OzZs+rZs6c2btyo4uJih/dU+jeFeXl5OnHihDp37ixJdm8tvBwPP/yw3f2wsDD99ttvys3NrfRaf/nLX2x/DggIUMuWLeXr66uBAwfatrds2VIBAQH66aefbNssFos8Pf/7klJUVKTffvtNfn5+atmypd1xBgQEKCsrSzt27LhkL3v27FF4eLhuvPFGrVmzRg0bNqz08QDAlbRmzRpduHBB48ePt70GStJDDz0kf39/rVy5UpL0zTff6Ndff9XYsWPl7e1t269Pnz5q1aqVbb/S1q9fr969e6tnz55KSUmRxWKpVG+l509BQYF+++033XTTTQoICCh3/owePdru0uFhYWEqKirS4cOHJf33rNLp06c1ePBg2ww9ceKE6tSpo06dOmn9+vXl1r7Y7CsqKtKqVat033336frrr7ftf8stt6h3796VOtbSmGO40ghQqFFeeukl7dmzRyEhIerYsaOmTp1qe3E8cOCAJGn48OEKDAy0uy1YsED5+fnKyclxeE8nT55UfHy8GjduLB8fHwUGBtreLuCoeqUHjyTbC/SpU6cqtY63t7cCAwPttlmtVgUHB5f5Pg6r1Wq3fnFxsebMmaMWLVrIYrHommuuUWBgoDIyMuyO86mnnpKfn586duyoFi1aaNy4cRf9DNq9996rBg0aaNWqVfL396/UsQCAM5SEi5YtW9ptr1evnpo1a2Z7/GL7SVKrVq1sj5fIy8tTnz59dMcdd2jp0qVVuoDR+fPn9dxzzykkJMTudfn06dPlzp9LzZKSORoZGVlmjqalpenXX3+1PdfM7Dt+/LjOnz+vFi1alOmlvJ+TGcwxOAOfgUKNMnDgQIWFhenTTz9VWlqakpKSNGvWLKWkpNjOLiUlJV30S3CvxBcXDhw4UFu2bNGkSZPUrl07+fn5qbi4WNHR0Q4741WnTp1ytxuG4ZB1zKw/c+ZMPfvssxo5cqRmzJihq666Sp6enho/frzdcd5yyy3av3+/vvjiC3355ZdasWKF3nrrLT333HOaNm2a3foPPPCA3nvvPS1evFh//etfK3UsAFCdWSwW3X333fr888/15Zdf6p577qn0Go8++qgWLlyo8ePH6//+7/9ktVrl4eGhQYMGlTt/LvVaX/KcDz74QE2aNCmzn5fX//6z0hmzrzzMMTgDAQo1zrXXXquxY8dq7Nix+vXXX3XnnXfqhRde0Jw5cyRJ/v7+uuuuu5zSy6lTp7R27VpNmzZNzz33nG17yW/xSqvoG9erw7exL1++XD169NA777xjt/306dNlPizr6+ur2NhYxcbG6sKFC+rXr59eeOEFJSQk2L21JSkpSV5eXho7dqwaNGhw0Q/nAoCr3HDDDZKk/fv3q1mzZrbtFy5c0MGDB23zpvR+kZGRdmvs37/f9ngJDw8PLV68WH379tWAAQOUmpqqiIiISvW2fPlyDR8+XLNnz7Zty8vLK/fqgGaUXMCoUaNGFc5Rs7MvMDBQPj4+5c7E/fv3V6nHy8Ecg1m8hQ81RlFRUZm3JDRq1EhBQUHKz89XaGiomjdvrpdffrncS8CWd6nWy1XyG68/ngmaO3dumX19fX0lqdzB5uvrW+WB5yx16tQpc5zLli0rc3neP17Ctl69emrdurUMw1BBQYHdYx4eHkpOTlb//v01fPhw/f3vf78yzQNAFd11112qV6+eXnvtNbvXwHfeeUc5OTnq06ePJKl9+/Zq1KiR5s2bp/z8fNt+qamp2rt3r22/0urVq6eUlBR16NBB9957r7Zv316p3sp7XX799ddVVFRUqXVK9O7dW/7+/po5c2aZ12vpf3PU7OyrU6eOevfurc8++0w///yzbfvevXu1atWqKvV4OZhjMIszUKgxzpw5o+DgYPXv319t27aVn5+f1qxZox07dmj27Nny9PTUggULFBMTo1tvvVUjRozQddddpyNHjmj9+vXy9/fXP/7xD4f25O/vb7uUakFBga677jqlpaXp4MGDZfYNDQ2VJD399NMaNGiQ6tatq3vvvVe+vr4KDQ3VmjVr9MorrygoKEhNmzZVp06dHNrr5brnnns0ffp0jRgxQl26dNHu3bu1ePFiu9/ISlJUVJSaNGmirl27qnHjxtq7d6/eeOMN9enTRw0aNCizrqenpz788EPdd999GjhwoP75z3+W+e0tALhKYGCgEhISNG3aNEVHR+tPf/qT9u/fr7feeksdOnTQgw8+KEmqW7euZs2apREjRig8PFyDBw+2Xcb8xhtv1OOPP17u+j4+Pvriiy8UGRmpmJgYbdiwQbfddpup3u655x598MEHslqtat26tbZu3ao1a9bo6quvrtKx+vv76+2339af//xn3XnnnRo0aJACAwP1888/a+XKlerataveeOONSs2+adOm6csvv1RYWJjGjh2rwsJC23csZWRkVKnPqmKOwTTXXPwPcLz8/Hxj0qRJRtu2bY0GDRoYvr6+Rtu2bY233nrLbr+dO3ca/fr1M66++mrDYrEYN9xwgzFw4EBj7dq1tn0ceRnzrKws4/777zcCAgIMq9VqDBgwwMjOzi5z+VTDMIwZM2YY1113neHp6WlXf9++fUb37t0NHx8fQ5LtkualL5NaWnn9X8rFji88PLzcy7XecMMNRp8+fWz38/LyjAkTJhjXXnut4ePjY3Tt2tXYunWrER4eboSHh9v2mz9/vtG9e3fbz7958+bGpEmTjJycHNs+5R3XuXPnjPDwcMPPz8/Ytm2b6eMCAEcr7zX2jTfeMFq1amXUrVvXaNy4sTFmzBjj1KlTZZ77ySefGHfccYdhsViMq666yhg6dKiRlZVlt095r8cnTpwwWrdubTRp0sQ4cOCAqT5PnTpljBgxwrjmmmsMPz8/o3fv3sa+ffuMG264we6rMUqOZ8eOHXbPX79+vSHJWL9+fZntvXv3NqxWq+Ht7W00b97ciIuLM7755hvbPpWZfRs2bDBCQ0ONevXqGc2aNTPmzZtnmwOVwRyDs3gYRiU/ZQ4AAAAAtRSfgQIAAAAAk/gMFFBFOTk5On/+fIX7lHeZV2erLn0CAMz5/fffy70YUmmBgYEXvXR3dcMcg7vhLXxAFcXFxem9996rcB93+OdVXfoEAJgzderUMt839EcHDx7UjTfe6JyGrjDmGNwNAQqoou+//17Z2dkV7uOs75uqSHXpEwBgzk8//aSffvqpwn26detm931E1RlzDO6GAAUAAAAAJnERCQAAAAAwiQAFAAAAACYRoGCzZ88excXFObXmoUOHlJaWJklq3769U2vXVl9//bW6du2qO++8Ux9++KGr2wGAi3LFXJKYTa7AbEJ1QoAqJT09XSEhIUpOTlZERITCwsLUvXt3DRkyREVFRZKk3bt3q2fPngoPD9c999yjzMxMSVJGRoa6d++u8PBwdenSRUeOHNH333+vdu3aaeLEiaZq/vFFuuR+XFycYmJiymxPT0+3rb1161Z17dpVp0+f1rBhwxQcHOy4H8wVVHpIXQm1/edbnmuvvVbr1q3Tli1b9Oqrr172euX9u4mIiFBERIRycnJUXFysZ555RmFhYerWrZtee+0123MnTpyorl27qlu3bpoxY4Yk6cknn1RAQECFl+gtr2bHjh1ta0hSly5dNH36dNv9RYsWqUWLFoqMjFRYWJjmz59veywqKsrUfyS5om5tqYmLYzY5H7PJ+ZhNzCZ3rHlRBmzWr19vTJgwwTAMwwgPDzfOnDljGIZhPPTQQ8amTZuMCxcuGLfffrvxww8/GIZhGJs3bza6d+9uGIZh9O/f39izZ49hGIZx7tw54/z582XWvFTN0NBQu8dK7g8fPty47bbbjF27dtltL3luRkaG0aFDB+PYsWNlnnspBQUFxoABA4yePXsaI0eONIYPH258/PHHRseOHY1OnToZX375pWEYhrFjxw4jIiLC6Natm5GUlGQYhmG8/fbbRocOHYwePXoYKSkppur90cCBA43g4GAjPDzcaNWqlTFs2DCjbdu2xocffmgYhmH8+OOPRlRUlBEeHm6MHz++0uu7+udb2tatW42OHTsaERERxpQpU4zHH3/c6N69u9GhQwdj586dxq+//mrcfffdtv0jIyONnJycStcxa8OGDcbQoUMve52L/bspkZycbIwZM8YwjP/+fbv77ruN1atXG3v27DH69+9v2+/kyZO2P5e3zqVqFhQUGLfffruRmZlp/Pzzz8aAAQOMHj162J6zcOFC4/XXXzcMwzDOnj1rREVFGV988YXtcTP/n7qibm2piYurbbPJ1XPJMGrPbHK3uWQYzCZmk3vVvBjOQJlw5swZ+fv7a9u2bWrXrp2aN28uSeratauKi4uVmZkpHx8frVmzRmfPnpWPj4/DLx06ceJEvfTSS2W2Hzx4UCNHjtTSpUvVuHHjSq/72Wef6aabbtKaNWvUoUMHFRUVKTExURs2bFBaWpqefvppSdLkyZOVkpKiTZs2acOGDfrll1+0dOlSrVmzRuvWrVPfvn2rdFxjxoxRbGys0tPTdezYMb3++uvauHGj7TdBkydP1ltvvaX09HTl5eXpm2++qVKdS7lSP9/SVq5cqSlTpmj9+vV67rnn9Pzzz2vDhg2aP3++kpKSFBgYqHr16uno0aP66aef1KhRI/n7+19WzYs5fvy4Jk2apDlz5lyR9UtbsmSJJk2aJEny8vLSE088oY8//lje3t46cOCA9u7dK0lq2LDhZdXx8vJS69atdeTIES1fvlxDhw5Vq1attG/fvjL71q9fX0899ZRWrFhxWTVdVbe21ETFaupscvVckmrPbHKnuSQxm5hN1aOmxFv4KhQTE6M77rhDWVlZuuWWW5Sdna2goCC7fYKDg5Wdna2kpCTt3btXbdu2VWxsrM6ePevQXkJDQ3XixAkdPnzYbvvatWvVqVOnKn9Z3g8//KDQ0FBJUocOHXT8+HFdf/318vb2lr+/v+rWravCwkJlZGTo/vvvV0REhH7++WdlZmbqxRdfVHx8vOLi4nTgwIHLPUQ1a9ZM/v7+8vf3t70tZd++fRo1apQiIiK0fft2ZWVlXXad8lypn29p48aN0z//+U8NHTpUX375pZKSkhQWFqbHHnvM9v0WDz74oD7++GMtXrxYQ4cOveyaF7N+/XoNHTpUgYGBDl87JiZGERERtree/PHfTcm/mebNm2vy5MkaO3asbr75Zn3++eeXVffcuXPKyMhQs2bNlJaWpujoaA0ePFjLli0rd/+goCAdPXr0smq6qm5tqYny1fTZ5E5zSarZs8md5pLEbJKYTdWhpiR5XfYKNVhqaqr8/Pz02muvafbs2erSpYv++c9/2u2TlZWloKAgNW7cWPPmzZMkPfPMM/rggw/08MMPV6qeh4eH7c95eXny8fGxe3zChAmaPXu23baRI0fq4MGDevfddzVy5MhK1ZOkm266STt37tQDDzygb775RoGBgdq1a5fy8vJ04cIFXbhwQV5eXmrbtq2WL18uq9WqoqIieXp6Ki8vTwsXLtSWLVs0a9Ysvfvuu5WuX7duXdtAKn38JVq2bKmXX35ZN9xwgwzDsO1bFa74+ZZmtVr1xhtv6MKFCwoNDZXVatXmzZv1r3/9SxMmTJAk3XvvvYqJiVFBQYESEhIuq15FWrRoYftttaOV/Lspce211yo7O1tNmzaV9L9/M5I0aNAgDRo0SMeOHVPPnj2r/BvjmJgYeXp6atKkScrPz9eePXvUt29fGYahnJwcPfvss2WeU95/dFaHurWlJi6ups8mV88lqfbMJneaSxKzSWI2uXvNEgQoExo2bKhDhw6pc+fOGjdunH788Uc1b95cX331lSQpJCREBw4cUIsWLSRJgYGBMqrw/cRNmzbVd999p3bt2mnz5s1q06aN3eO9evXS9OnTdfLkSds2T09PLV68WHfddZeCg4MVFRVVqZr33XeflixZop49e+rmm29WnTp1NHnyZHXv3l2enp56/vnnJUkvvvii+vXrp+LiYlksFn366acaM2aMDh06pPz8fL3wwguVPl5JatOmjRISEjRgwACdPn26zOOzZs3Sww8/rLy8PNWpU0fvvvuurr/++irVcsXPt7T58+crJSVFhYWFiouL04YNGxQREaHOnTvb9qlXr55atWolT09PeXlduX+ev/zyi86fP2/7Le+VNGjQIL388st68803VVhYqFdeeUXjx4/XyZMnZRiGrr76agUEBKhu3bpVrlF6MM6dO1dz5sxR//79JUljx47V/v377fY/f/68kpKSFB8fX/UDc1Hd2lITl1ZTZ5Or55JUe2aTO80lidnEbHL/miUIUBWIiYlRnTp1VFxcrPfee0/16tXThx9+qIceekhFRUXy9fW1XWpzyZIl+uKLL+Tj46OAgIAqXYJz5syZGjNmjAoLC+Xj46MFCxaU2eeRRx7RoEGD7LbVr19fn376qaKiotSkSRPdfvvtpmt6eXlp+fLlZbYPGTLE7n5oaKjWrl1rt23RokWm61yMv7+/Nm7cWGZ7yfvJmzVrptTU1MuuI7nm51va+PHjNX78eNv9kt/u/ZGnp6eGDx9epRpmRUdHX7G1S/7dSNL777+vUaNG6ZlnnlG3bt1kGIYGDBigXr166eDBgxo+fLgMw1BhYaHtcw2Xa8WKFfrss89s93v06KGlS5cqJCREr776qlJSUlRQUKBhw4Y59Ofgirq1pSbs1fTZ5Oq5JNWe2eROc0liNjGbqlHNKl16oobaunWrcfvttxvz5893yHr//ve/jU6dOhkvvPCC02oahmH8+c9/Njp06OCw9aqz6vbzHTNmjDFkyJArsvaV4uif8aRJk4yWLVsaZ8+edVrNXr16Gffee+8l93NF3dpSExfHbKp5qtPPtzrOJcNgNl3purWl5sV4GEYVzucDAAAAQC3EVfgAAAAAwCQCFAAAAACYRIACAAAAAJMIUFWUn5+v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oBZgNgEAyuPl6gYkaebMmRozZowKCwvl4+OjBQsWlNnnkUce0aBBg+y21a9fX59++qmioqLUpEkT3X777c5qGQBQwzGbAADl8TAMw3BF4W3btumvf/2rxo0bd8mrHZk1bNgw7du3T9u3bze1f25urqxWqzr2Ximvur4O6QHAlZGQ6pjXCbiHc0aRYot/VE5Ojlt95ofZhJqG107APLOzyWVnoDp37qxdu3Y5dM3333/foesBAGoXZhMA4FLc4jNQAAAAAFAdEKAAAAAAwCQCFAAAAACYRIACAAAAAJMIUAAAAABgEgEKAAAAAEwiQAEAAACASS77HigAAABcWYkxyU6vyZf3oqbjDBQAAAAAmESAAgAAAACTCFAAAAAAYBIBCgAAAABMIkABAAAAgEkEKAAAAAAwiQAFAAAAACYRoAAAAADApCoFqMzMTGVlZdnub9++XePHj1dysvO/rA0AAOYSAMBZqhSghgwZovXr10uSjh07pl69emn79u16+umnNX36dIc2CADApTCXAADOUqUAtWfPHnXs2FGStHTpUt12223asmWLFi9erEWLFjmyPwAALom5BABwlioFqIKCAlksFknSmjVr9Kc//UmS1KpVKx09etRx3QEAYAJzCQDgLFUKULfeeqvmzZunTZs2afXq1YqOjpYkZWdn6+qrr3ZogwAAXApzCQDgLFUKULNmzdL8+fMVERGhwYMHq23btpKkv//977a3UDjKtm3b1KlTJ/Xo0UNTp07VE088ofDwcHXs2FHfffedjh8/rj59+tj279mzp3Jzc8tdKz8/X7m5uXY3AED158y5JDGbAKA286rKkyIiInTixAnl5uaqYcOGtu2jR49W/fr1HdacJK1cuVJTpkzR3XffreLiYuXl5al+/frauXOnkpKStHjxYtWrV09Hjx7V+fPn1ahRI/n7+5e7VmJioqZNm+bQ/gAArufMuSQxmwCgNvMwDMOo7JOmTJmikSNH6oYbbrgSPdk5duyYnn/+eZ06dUpDhw7Vjh07tGbNGkmSl5eX1q9frxUrVujw4cM6e/as7rjjDt1zzz3lrpWfn6/8/Hzb/dzcXIWEhKhj75Xyqut7xY8FQNUlpI52dQtwoHNGkWKLf1ROTs5Fg0VlOHMuScwmoCK8XqO6MjubqhSg2rVrpz179ig8PFyjRo3SAw88YPvwrqOdP39ePj4+unDhgkJDQ2W1WrV582b961//0oQJE5Senq4LFy4oJiZGBQUFWrdunby8zJ1Yy83NldVqZUgB1QADuWZxdIBy5lySmE1ARXi9RnVldjZV6TNQ3333nXbs2KFbb71V8fHxatKkicaMGaMdO3ZUueGLmT9/vrp3766IiAjFxcXpqquuUkREhJYtW2bbp169emrVqpXatm1rekABAGoOZ84lidkEALVZlc5AlVZQUKB//OMfWrhwoVatWqVWrVpp1KhRiouLk9VqdVSfl/Too49q+PDhat++venn8Fs+oPrgN5o1i6PPQJXmLnNJYjahduL1GtXVFT0DVZphGCooKNCFCxdkGIYaNmyoN954QyEhIfrkk08ud3lTxo4dq5MnT1ZqQAEAaiZ3mEsSswkAaqoqv6fgX//6lxYuXKiPP/5YFotFw4YN05tvvqmbbrpJkvT666/rscceU2xsrMOavZi33nrritcAALg3d5pLErMJAGqqKp2BatOmjTp37qyDBw/qnXfeUWZmpl588UXbkJKkwYMH6/jx4w5rFACAi2EuAQCcpUpnoAYOHKiRI0fquuuuu+g+11xzjYqLi6vcGAAAZjGXAADOUukzUAUFBVq0aBHflA4AcAvMJQCAM1U6QNWtW1d5eXlXohcAACqNuQQAcKYqfQZq3LhxmjVrlgoLCx3dDwAAlcZcAgA4S5U+A7Vjxw6tXbtWaWlpatOmjXx97b+nIiUlxSHNAQBgBnMJAOAsVQpQAQEBeuCBBxzdCwAAVcJcAgA4S5UC1MKFCx3dBwAAVcZcAtxHYkyyS+ompI52SV3UPlX6DJQkFRYWas2aNZo/f77OnDkjScrOztbvv//usOYAADCLuQQAcIYqnYE6fPiwoqOj9fPPPys/P1+9evVSgwYNNGvWLOXn52vevHmO7hMAgItiLgEAnKVKZ6Di4+PVvn17nTp1Sj4+Prbt999/v9auXeuw5gAAMIO5BABwliqdgdq0aZO2bNmievXq2W2/8cYbdeTIEYc0BgCAWcwlAICzVOkMVHFxsYqKispsz8rKUoMGDS67KQAAKoO5BABwlioFqKioKM2dO9d238PDQ7///rumTJmiu+++21G9AQBgCnMJAOAsVXoL3+zZs9W7d2+1bt1aeXl5GjJkiA4cOKBrrrlGH3/8saN7BACgQswlAICzVClABQcHa9euXVqyZIkyMjL0+++/a9SoURo6dKjdh3cBAHAG5hIAwFmqFKAkycvLSw8++KAjewEAoMqYSwAAZ6hSgHr//fcrfHzYsGFVagYAgKpgLgEAnKVKASo+Pt7ufkFBgc6dO6d69eqpfv36DCoAgFMxlwAAzlKlq/CdOnXK7vb7779r//796tatm8s+rPv111+ra9euuvPOO/Xhhx+6pAcAgGu441ySmE0AUBNVKUCVp0WLFnrxxRfL/BbQWa699lqtW7dOW7Zs0auvvuqSHgAA7sPVc0liNgFATVTli0iUu5iXl7Kzsx25pGnXX3+9JGnjxo1q2bJlufvk5+crPz/fdj83N9cpvQEAXMOVc0liNgFATVSlAPX3v//d7r5hGDp69KjeeOMNde3a1SGNVcXx48c1adIkffHFF+U+npiYqGnTpjm5KwDAleauc0liNgFATVOlAHXffffZ3ffw8FBgYKAiIyM1e/ZsR/RVJevXr9fQoUMVGBhY7uMJCQl64oknbPdzc3MVEhLirPYAAFeIu84lidkEADVNlQJUcXGxo/twiBYtWqh58+YXfdxischisTixIwCAM7jrXJKYTQBQ01QpQJX+TdmlvPLKK1UpUSW//PKLzp8/r9DQUKfVBAC4nrvOJYnZBAA1TZUC1M6dO/Xtt9+qsLDQ9qHY//znP6pTp47uvPNO234eHh6O6dKk6Ohop9YDALgHd51LErMJAGqaKgWoe++9Vw0aNNB7772nhg0bSvrvd3CMGDFCYWFhmjBhgkObBACgIswlAICzVOl7oGbPnq3ExETbkJKkhg0b6vnnn3f5h3UBALUPcwkA4CxVClC5ubk6fvx4me3Hjx/XmTNnLrspAAAqg7kEAHCWKgWo+++/XyNGjFBKSoqysrKUlZWlFStWaNSoUerXr5+jewQAoELMJQCAs1TpM1Dz5s3TxIkTNWTIEBUUFPx3IS8vjRo1SklJSQ5tEACAS2EuAQCcpUoBqn79+nrrrbeUlJSkH3/8UZLUvHlz+fr6OrQ5AADMYC4BAJylSgGqhK+vr26//XZH9QIAwGVhLgEArrQqfQYKAAAAAGojAhQAAAAAmESAAgAAAACTLuszUAAAAIA7SIxJdnrNhNTRTq8J1+MMFAAAAACYRIACAAAAAJMIUAAAAABgEgEKAAAAAEwiQAEAAACASQQoAAAAADCJAAUAAAAAJhGgAAAAAMAkAhQAAAAAmESAAgAAAACTCFAAAAAAYBIBCgAAAABMcmmASk9PV0hIiJKTkxUREaGwsDBFREQoIiJCOTk5Ki4u1jPPPKOwsDB169ZNr732mu25EydOVNeuXdWtWzfNmDFDkvTkk08qICBAv//+e7n18vPzlZuba3cDAKA0ZhMAoCJerm4gNjZWo0eP1kcffaTU1FT5+fnZHvvb3/6mkydPatOmTSosLFTfvn3VunVrXXvttTp8+LC++uorSdKpU6ckSS+99JK2b99+0VqJiYmaNm3alT0gAEC1x2wCAFyMW7+Fb8mSJZo0aZIkycvLS0888YQ+/vhjeXt768CBA9q7d68kqWHDhqbWS0hIUE5Oju2WmZl5xXoHANRMzCYAqN3cKkDFxMQoIiJCMTExkqTs7GwFBQXZHg8ODlZ2draaN2+uyZMna+zYsbr55pv1+eefm1rfYrHI39/f7gYAQEWYTQCA0lz+Fr7S/vg2iWuvvVbZ2dlq2rSpJCkrK8s2tAYNGqRBgwbp2LFj6tmzp/r27euSngEANRuzCQBQmludgfqjQYMG6eWXX5YkFRYW6pVXXtGgQYN08uRJ/fbbb5KkgIAA1a1b15VtAgBqEWYTANRubnUGKiYmRnXq1JEkvf/++xo1apSeeeYZdevWTYZhaMCAAerVq5cOHjyo4cOHyzAMFRYW6umnn3Zx5wCAmorZBAAozaUBytvbW6tXr1ZycrLS09PL3ScxMbHMtqZNm2rjxo1ltj/55JM6duyYPD3d+sQaAMCNMZsAABXxMAzDcHUTrpKbmyur1aqOvVfKq66vq9sBUIGE1NGubgEOdM4oUmzxj8rJyeGiCX/AbAKqD2ZTzWJ2NvHrMAAAAAAwiQAFAAAAACYRoAAAAADAJAIUAAAAAJhEgAIAAAAAkwhQAAAAAGASAQoAAAAATHLpF+kCAAAA1VViTLJL6vL9U67FGSgAAAAAMIkABQAAAAAmEaAAAAAAwCQCFAAAAACYRIACAAAAAJMIUAAAAABgEgEKAAAAAEwiQAEAAACASQQoAAAAADCJAAUAAAAAJhGgAAAAAMAkAhQAAAAAmOTSAJWenq6QkBAlJycrIiJCYWFh6tixo2bMmGHbp0uXLpo+fbrt/qJFi9SiRQtFRkYqLCxM8+fPtz0WFRWl9u3bO/UYAAA1C7MJAFARl5+Bio2N1ejRoyVJqamp2rJli5YvX66srCxlZmYqODhY6enpds+Jj4/XunXrtGrVKqWkpGjlypWSpLS0tApr5efnKzc31+4GAMAfMZsAABfj8gD1R15eXmrdurWOHDmi5cuXa+jQoWrVqpX27dtXZt/69evrqaee0ooVK0ytnZiYKKvVaruFhIQ4un0AQA3EbAIAlHC7AHXu3DllZGSoWbNmSktLU3R0tAYPHqxly5aVu39QUJCOHj1qau2EhATl5OTYbpmZmY5sHQBQQzGbAAAlvFzdQGkxMTHy9PTUpEmTlJ+frz179qhv374yDEM5OTl69tlnyzwnOztbQUFBpta3WCyyWCyObhsAUIMxmwAApblVgEpNTZWfn58kae7cuZozZ4769+8vSRo7dqz2799vt//58+eVlJSk+Ph4p/cKAKgdmE0AgNLc7i18JVasWKEePXrY7vfo0UNLly6VJL366quKjIxUVFSU+vXrp+joaFe1CQCoRZhNAACXnoHy9vbW6tWrlZycXOZqRps2bbK7P2DAANuf4+Liyl0vKirK9FsmAAAoD7MJAFARlwaozp07a9euXQ5b71KXigUA4FKYTQCAirjtW/gAAAAAwN0QoAAAAADAJAIUAAAAAJhEgAIAAAAAkwhQAAAAAGASAQoAAAAATCJAAQAAAIBJBCgAAAAAMMmlX6QLAAAAoHISY5KdXjMhdbTTa7orzkABAAAAgEkEKAAAAAAwiQAFAAAAACYRoAAAAADAJAIUAAAAAJhEgAIAAAAAkwhQAAAAAGASAQoAAAAATCJAAQAAAIBJBCgAAAAAMIkABQAAAAAmuTRApaenKyQkRMnJyYqIiFBYWJg6duyoGTNm2Pbp0qWLpk+fbru/aNEitWjRQpGRkQoLC9P8+fNtj0VFRal9+/ZOPQYAQM3CbAIAVMTlZ6BiY2M1evRoSVJqaqq2bNmi5cuXKysrS5mZmQoODlZ6errdc+Lj47Vu3TqtWrVKKSkpWrlypSQpLS2twlr5+fnKzc21uwEA8EfMJgDAxbg8QP2Rl5eXWrdurSNHjmj58uUaOnSoWrVqpX379pXZt379+nrqqae0YsUKU2snJibKarXabiEhIY5uHwBQAzGbAAAl3C5AnTt3ThkZGWrWrJnS0tIUHR2twYMHa9myZeXuHxQUpKNHj5paOyEhQTk5ObZbZmamI1sHANRQzCYAQAkvVzdQWkxMjDw9PTVp0iTl5+drz5496tu3rwzDUE5Ojp599tkyz8nOzlZQUJCp9S0WiywWi6PbBgDUYMwmAEBpbhWgUlNT5efnJ0maO3eu5syZo/79+0uSxo4dq/3799vtf/78eSUlJSk+Pt7pvQIAagdmEwCgNLd7C1+JFStWqEePHrb7PXr00NKlSyVJr776qiIjIxUVFaV+/fopOjraVW0CAGoRZhMAwKVnoLy9vbV69WolJyeXuZrRpk2b7O4PGDDA9ue4uLhy14uKijL9lgkAAMrDbAIAVMSlAapz587atWuXw9a71KViAQC4FGYTAKAibvsWPgAAAABwNwQoAAAAADCJAAUAAAAAJhGgAAAAAMAkAhQAAAAAmESAAgAAAACTCFAAAAAAYBIBCgAAAABMcukX6QIAAABwf4kxyS6pm5A62iV1K8IZKAAAAAAwiQAFAAAAACYRoAAAAADAJAIUAAAAAJhEgAIAAAAAkwhQAAAAAGASAQoAAAAATCJAAQAAAIBJBCgAAAAAMIkABQAAAAAmEaAAAAAAwCQCFAAAAACY5NIAlZ6erpCQECUnJysiIkJhYWHq2LGjZsyYYdunS5cumj59uu3+okWL1KJFC0VGRiosLEzz58+3PRYVFaX27ds79RgAADULswkAUBGXn4GKjY3V6NGjJUmpqanasmWLli9frqysLGVmZio4OFjp6el2z4mPj9e6deu0atUqpaSkaOXKlZKktLS0Cmvl5+crNzfX7gYAwB8xmwAAF+PyAPVHXl5eat26tY4cOaLly5dr6NChatWqlfbt21dm3/r16+upp57SihUrTK2dmJgoq9Vqu4WEhDi6fQBADcRsAgCUcLsAde7cOWVkZKhZs2ZKS0tTdHS0Bg8erGXLlpW7f1BQkI4ePWpq7YSEBOXk5NhumZmZjmwdAFBDMZsAACW8XN1AaTExMfL09NSkSZOUn5+vPXv2qG/fvjIMQzk5OXr22WfLPCc7O1tBQUGm1rdYLLJYLI5uGwBQgzGbAACluVWASk1NlZ+fnyRp7ty5mjNnjvr37y9JGjt2rPbv32+3//nz55WUlKT4+Hin9woAqB2YTQCA0tzuLXwlVqxYoR49etju9+jRQ0uXLpUkvfrqq4qMjFRUVJT69eun6OhoV7UJAKhFmE0AAJeegfL29tbq1auVnJxc5mpGmzZtsrs/YMAA25/j4uLKXS8qKsr0WyYAACgPswkAUBGXBqjOnTtr165dDlvvUpeKBQDgUphNAICKuO1b+AAAAADA3RCgAAAAAMAkAhQAAAAAmESAAgAAAACTCFAAAAAAYBIBCgAAAABMIkABAAAAgEkEKAAAAAAwyaVfpAsAAAAAF5MYk+y0WoUFZ6VVfS65H2egAAAAAMAkAhQAAAAAmESAAgAAAACTCFAAAAAAYBIBCgAAAABMIkABAAAAgEkEKAAAAAAwiQAFAAAAACYRoAAAAADAJAIUAAAAAJhEgAIAAAAAk1waoNLT0xUSEqLk5GRFREQoLCxMHTt21IwZM2z7dOnSRdOnT7fdX7RokVq0aKHIyEiFhYVp/vz5tseioqLUvn17px4DAKBmYTYBACri8jNQsbGxGj16tCQpNTVVW7Zs0fLly5WVlaXMzEwFBwcrPT3d7jnx8fFat26dVq1apZSUFK1cuVKSlJaWVmGt/Px85ebm2t0AAPgjZhMA4GJcHqD+yMvLS61bt9aRI0e0fPlyDR06VK1atdK+ffvK7Fu/fn099dRTWrFiham1ExMTZbVabbeQkBBHtw8AqIGYTQCAEm4XoM6dO6eMjAw1a9ZMaWlpio6O1uDBg7Vs2bJy9w8KCtLRo0dNrZ2QkKCcnBzbLTMz05GtAwBqKGYTAKCEl6sbKC0mJkaenp6aNGmS8vPztWfPHvXt21eGYSgnJ0fPPvtsmedkZ2crKCjI1PoWi0UWi8XRbQMAajBmEwCgNLcKUKmpqfLz85MkzZ07V3PmzFH//v0lSWPHjtX+/fvt9j9//rySkpIUHx/v9F4BALUDswkAUJrbvYWvxIoVK9SjRw/b/R49emjp0qWSpFdffVWRkZGKiopSv379FB0d7ao2AQC1CLMJAODSM1De3t5avXq1kpOTy1zNaNOmTXb3BwwYYPtzXFxcuetFRUWZfssEAADlYTYBACri0gDVuXNn7dq1y2HrXepSsQAAXAqzCQBQEbd9Cx8AAAAAuBsCFAAAAACYRIACAAAAAJMIUAAAAABgEgEKAAAAAEwiQAEAAACASQQoAAAAADDJpd8D5WqGYUiSigrPubgTAJdyzihydQtwoHNGsaT/vQ7jf5hNAOAaJa+7l5pNHkYtnl5ZWVkKCQlxdRsAUGtlZmYqODjY1W24FWYTALjWpWZTrQ5QxcXFys7OVoMGDeTh4VGp5+bm5iokJESZmZny9/e/Qh3Wzpquqltbarqqbm2p6aq61a2mYRg6c+aMgoKC5OnJu8lLq+ps4u97zavpqrq1paar6nKs7lvT7Gyq1W/h8/T0vOzffPr7+zv1L39tqumqurWlpqvq1paarqpbnWpardYr0E31d7mzib/vNa+mq+rWlpquqsuxumdNM7OJX/sBAAAAgEkEKAAAAAAwiQBVRRaLRVOmTJHFYqFmDalbW2q6qm5tqemqurWlJi6Ov+81r6ar6taWmq6qy7FW/5q1+iISAAAAAFAZnIECAAAAAJMIUAAAAABgEgEKAAAAAEwiQAEAAACASQQowA1ERERo/Pjxrm4DAABJzCWgIgQoAAAAADCJAAUAAAAAJhGgADe0cuVKWa1WLV68WJmZmRo4cKACAgJ01VVXqW/fvjp06JAkaePGjapbt66OHTtm9/zx48crLCxMknT48GHde++9atiwoXx9fXXrrbfqn//8p7MPCQBQjTGXgP8hQAFu5qOPPtLgwYO1ePFiDRw4UL1791aDBg20adMmffXVV/Lz81N0dLQuXLig7t27q1mzZvrggw9szy8oKNDixYs1cuRISdK4ceOUn5+vjRs3avfu3Zo1a5b8/PxcdXgAgGqGuQTY83J1AwD+580339TTTz+tf/zjHwoPD9eHH36o4uJiLViwQB4eHpKkhQsXKiAgQOnp6YqKitKoUaO0cOFCTZo0SZL0j3/8Q3l5eRo4cKAk6eeff9YDDzygNm3aSJKaNWvmmoMDAFQ7zCWgLM5AAW5i+fLlevzxx7V69WqFh4dLknbt2qUffvhBDRo0kJ+fn/z8/HTVVVcpLy9PP/74oyQpLi5OP/zwg7Zt2yZJWrRokQYOHChfX19J0mOPPabnn39eXbt21ZQpU5SRkeGaAwQAVCvMJaB8BCjATdxxxx0KDAzUu+++K8MwJEm///67QkND9d1339nd/vOf/2jIkCGSpEaNGunee+/VwoUL9csvvyg1NdX2NglJ+stf/qKffvpJf/7zn7V79261b99er7/+ukuOEQBQfTCXgPIRoAA30bx5c61fv16ff/65Hn30UUnSnXfeqQMHDqhRo0a66aab7G5Wq9X23L/85S/65JNPlJycrObNm6tr1652a4eEhOjhhx9WSkqKJkyYoL/97W9OPTYAQPXDXALKR4AC3MjNN9+s9evXa8WKFRo/fryGDh2qa665Rn379tWmTZt08OBBpaen67HHHlNWVpbteb1795a/v7+ef/55jRgxwm7N8ePHa9WqVTp48KC+/fZbrV+/XrfccouzDw0AUA0xl4CyuIgE4GZatmypdevWKSIiQnXq1NHGjRv11FNPqV+/fjpz5oyuu+469ezZU/7+/rbneHp6Ki4uTjNnztSwYcPs1isqKtK4ceOUlZUlf39/RUdHa86cOc4+LABANcVcAux5GCVvagVQrY0aNUrHjx/X3//+d1e3AgAAcwk1FmeggGouJydHu3fv1kcffcSQAgC4HHMJNR0BCqjm+vbtq+3bt+vhhx9Wr169XN0OAKCWYy6hpuMtfAAAAABgElfhAwAAAACTCFAAAAAAYBIBCgAAAABMIkABAAAAgEkEKAAAAAAwiQAFAAAAACYRoAAAAADAJAIUAAAAAJj0/88tOrY0mrt/AAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "#通过下面代码查看mask的效果\n",
    "inputs_words = [\"The quick brown fox jumps over the lazy dog .\", \"What does the fox say ?\"]\n",
    "\n",
    "inputs_ids, input_mask = tokenizer.encode([w.split() for w in inputs_words], return_mask=True)\n",
    "for i in range(len(inputs_words)):\n",
    "    decode_text = tokenizer.decode(inputs_ids[i: i+1].tolist(), remove_bos=False, remove_eos=False, remove_pad=False, split=True)[0]\n",
    "    print(decode_text)\n",
    "    # print(input_mask[i].reshape(1, -1))\n",
    "    self_attn_mask  = input_mask[i].reshape(1, -1).repeat_interleave(inputs_ids.shape[-1], dim=0)\n",
    "    # print(input_mask[i].reshape(1, -1).repeat_interleave(inputs_ids.shape[-1], dim=0))\n",
    "    look_ahead_mask = generate_square_subsequent_mask(inputs_ids.shape[-1])\n",
    "\n",
    "    fig, axs = plt.subplots(1, 2, figsize=(10, 5))\n",
    "    axs[0].matshow(self_attn_mask, cmap='coolwarm')\n",
    "    axs[0].set_title(\"self_attn_mask\")\n",
    "    axs[0].set_yticks(range(len(decode_text)), decode_text, fontsize=6)\n",
    "    axs[0].set_ylabel(\"querys\")\n",
    "    axs[0].set_xticks(range(len(decode_text)), decode_text, fontsize=6)\n",
    "    axs[0].set_xlabel(\"keys\")\n",
    "    axs[1].matshow(look_ahead_mask, cmap='coolwarm')\n",
    "    axs[1].set_title(\"look_ahead_mask\")\n",
    "    axs[1].set_yticks(range(len(decode_text)), decode_text, fontsize=6)\n",
    "    axs[1].set_ylabel(\"querys\")\n",
    "    axs[1].set_xticks(range(len(decode_text)), decode_text, fontsize=6)\n",
    "    axs[1].set_xlabel(\"keys\")\n",
    "    plt.show()\n",
    "    print('-'*50)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d24a059aabab0920",
   "metadata": {},
   "source": [
    "没有mask行部分padding因为在计算loss时会进行处理，这里处理反而会变得更复杂，所以这里只展示了列`padding_mask`的效果<"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7aadcf5bbcb859dd",
   "metadata": {},
   "source": [
    "## Transformer模型<br>\n",
    "Transformer模型是一种基于注意力机制的深度学习模型，它使用了多头注意力机制和前馈神经网络等模块来实现序列到序列的转换。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "a3c2c0228e57ad2a",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:23:23.119824Z",
     "start_time": "2025-03-13T11:23:23.107178Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:40.957573Z",
     "iopub.status.busy": "2025-03-13T12:13:40.957377Z",
     "iopub.status.idle": "2025-03-13T12:13:40.974268Z",
     "shell.execute_reply": "2025-03-13T12:13:40.973773Z",
     "shell.execute_reply.started": "2025-03-13T12:13:40.957553Z"
    }
   },
   "outputs": [],
   "source": [
    "@dataclass\n",
    "class TransformerOutput:\n",
    "    logits: Tensor\n",
    "    encoder_last_hidden_states: Tensor\n",
    "    encoder_attn_scores: List[Tensor] #画图\n",
    "    decoder_last_hidden_states: Tensor\n",
    "    decoder_self_attn_scores: List[Tensor] #画图\n",
    "    decoder_cross_attn_scores: List[Tensor] #画图\n",
    "    preds: Optional[Tensor] = None\n",
    "\n",
    "class TransformerModel(nn.Module):\n",
    "    def __init__(self, config):\n",
    "        super().__init__()\n",
    "        # hyper params\n",
    "        self.hidden_size = config[\"d_model\"]\n",
    "        self.num_encoder_layers = config[\"num_encoder_layers\"]\n",
    "        self.num_decoder_layers = config[\"num_decoder_layers\"]\n",
    "        self.pad_idx = config[\"pad_idx\"]\n",
    "        self.bos_idx = config[\"bos_idx\"]\n",
    "        self.eos_idx = config[\"eos_idx\"]\n",
    "        self.vocab_size = config[\"vocab_size\"]\n",
    "        self.dropout_rate = config[\"dropout\"]\n",
    "        self.max_length = config[\"max_length\"]\n",
    "        self.share = config[\"share_embedding\"] # 是否共享词嵌入，共享后，decoder的词嵌入层和encoder的词嵌入层相同，节省内存\n",
    "\n",
    "        # layers\n",
    "        self.src_embedding = TransformerEmbedding(config) # 输入的嵌入层\n",
    "        if self.share:#如果共享词嵌入，则使用src_embedding作为trg_embedding\n",
    "            self.trg_embedding = self.src_embedding #源和目标的嵌入层相同，共享参数，节省内存\n",
    "            self.linear = lambda x: torch.matmul(\n",
    "                x, self.trg_embedding.get_word_embedding_weights().T\n",
    "            ) # 输出层，共享参数，直接拿原有embedding矩阵的转置，节省内存\n",
    "        else:\n",
    "            self.trg_embedding = TransformerEmbedding(config) #decoder模块的嵌入层\n",
    "            self.linear = nn.Linear(self.hidden_size, self.vocab_size) # 输出层\n",
    "\n",
    "        self.encoder = TransformerEncoder(config)\n",
    "        self.decoder = TransformerDecoder(config)\n",
    "\n",
    "        # init weights\n",
    "        self._init_weights()\n",
    "\n",
    "    def _init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化权重\"\"\"\n",
    "        for p in self.parameters():\n",
    "            if p.dim() > 1:\n",
    "                nn.init.xavier_uniform_(p)\n",
    "\n",
    "    def generate_square_subsequent_mask(self, sz: int) -> Tensor:\n",
    "        \"\"\"\n",
    "        Generate a square mask for the sequence. The masked positions are filled with True.\n",
    "            Unmasked positions are filled with False.为了生成斜三角的mask\n",
    "        \"\"\"\n",
    "        mask = (torch.triu(torch.ones(sz, sz)) == 0).transpose(-1, -2).bool()\n",
    "\n",
    "        return mask\n",
    "\n",
    "    def forward(\n",
    "        self, encoder_inputs, decoder_inputs, encoder_inputs_mask=None\n",
    "    ) -> TransformerOutput:\n",
    "        # encoder_inputs: [batch_size, src_len]\n",
    "        # decoder_inputs: [batch_size, trg_len]\n",
    "        # encoder_inputs_mask: [batch_size, src_len]\n",
    "        if encoder_inputs_mask is None:\n",
    "            encoder_inputs_mask = encoder_inputs.eq(self.pad_idx) # [batch_size, src_len]\n",
    "        encoder_inputs_mask = encoder_inputs_mask.unsqueeze(1).unsqueeze(\n",
    "            2\n",
    "        )  # [batch_size, 1, 1, src_len],用于encoder的自注意力\n",
    "        look_ahead_mask = self.generate_square_subsequent_mask(decoder_inputs.shape[1])\n",
    "        look_ahead_mask = (\n",
    "            look_ahead_mask.unsqueeze(0).unsqueeze(0).to(decoder_inputs.device)\n",
    "        )  #[trg_len, trg_len]--> [1, 1, trg_len, trg_len],用于decoder的自注意力\n",
    "        #增加decoder_inputs_mask和look_ahead_mask进行组合\n",
    "        decoder_inputs_mask = decoder_inputs.eq(self.pad_idx) # [batch_size, trg_len]，和上面encoder_inputs_mask一致\n",
    "        # print(decoder_inputs_mask.shape)\n",
    "        decoder_inputs_mask = decoder_inputs_mask.unsqueeze(1).unsqueeze(2)  # [batch_size, 1, 1, trg_len]\n",
    "        # print(decoder_inputs_mask.shape)\n",
    "        decoder_inputs_mask = decoder_inputs_mask + look_ahead_mask # [batch_size, 1, 1, trg_len]与[1, 1, trg_len, trg_len]相加，得到decoder的自注意力mask\n",
    "\n",
    "        # encoding\n",
    "        encoder_inputs_embeds = self.src_embedding(encoder_inputs)\n",
    "        encoder_outputs = self.encoder(encoder_inputs_embeds, encoder_inputs_mask) #encoder_inputs_mask用于encoder的自注意力,广播去做计算\n",
    "\n",
    "        # decoding\n",
    "        decoder_inputs_embeds = self.trg_embedding(decoder_inputs)\n",
    "        decoder_outputs = self.decoder(\n",
    "            decoder_inputs_embeds=decoder_inputs_embeds,\n",
    "            encoder_outputs=encoder_outputs.last_hidden_states,\n",
    "            attn_mask=decoder_inputs_mask, #用于decoder的自注意力,广播去做计算\n",
    "            cross_attn_mask=encoder_inputs_mask,#用于decoder的交叉注意力,广播去做计算\n",
    "        )\n",
    "\n",
    "        logits = self.linear(decoder_outputs.last_hidden_states) # [batch_size, trg_len, vocab_size]\n",
    "\n",
    "        return TransformerOutput(\n",
    "            logits=logits,\n",
    "            encoder_last_hidden_states=encoder_outputs.last_hidden_states,\n",
    "            encoder_attn_scores=encoder_outputs.attn_scores,\n",
    "            decoder_last_hidden_states=decoder_outputs.last_hidden_states,\n",
    "            decoder_self_attn_scores=decoder_outputs.self_attn_scores,\n",
    "            decoder_cross_attn_scores=decoder_outputs.cross_attn_scores,\n",
    "        )\n",
    "\n",
    "    @torch.no_grad()\n",
    "    def infer(self, encoder_inputs, encoder_inputs_mask=None) -> TransformerOutput:\n",
    "        # assert len(encoder_inputs.shape) == 2 and encoder_inputs.shape[0] == 1\n",
    "        if encoder_inputs_mask is None:#应对多个样本同时进行推理\n",
    "            encoder_inputs_mask = encoder_inputs.eq(self.pad_idx)\n",
    "        encoder_inputs_mask = encoder_inputs_mask.unsqueeze(1).unsqueeze(2)  # [batch_size, 1, 1, src_len],[1,src_len]相加时，会自动广播到[batch_size,1,src_len,src_len]\n",
    "        look_ahead_mask = self.generate_square_subsequent_mask(self.max_length)\n",
    "        look_ahead_mask = (\n",
    "            look_ahead_mask.unsqueeze(0).unsqueeze(0).to(encoder_inputs.device)\n",
    "        )  # [1, 1, trg_len, trg_len]\n",
    "\n",
    "        # encoding\n",
    "        encoder_inputs_embeds = self.src_embedding(encoder_inputs)\n",
    "        encoder_outputs = self.encoder(encoder_inputs_embeds) #因为只支持单样本预测，没有paddings，所以不需要mask\n",
    "\n",
    "        # decoding,多样本推理\n",
    "        decoder_inputs = torch.Tensor([self.bos_idx] * encoder_inputs.shape[0]).reshape(-1, 1).long().to(device=encoder_inputs.device)\n",
    "        for cur_len in tqdm(range(1, self.max_length + 1)):\n",
    "            decoder_inputs_embeds = self.trg_embedding(decoder_inputs)\n",
    "            decoder_outputs = self.decoder(\n",
    "                decoder_inputs_embeds=decoder_inputs_embeds,\n",
    "                encoder_outputs=encoder_outputs.last_hidden_states,\n",
    "                attn_mask=look_ahead_mask[:, :, :cur_len, :cur_len],#decoder的自注意力mask\n",
    "            )\n",
    "\n",
    "            logits = self.linear(decoder_outputs.last_hidden_states)\n",
    "            next_token = logits.argmax(dim=-1)[:, -1:] #通过最大下标确定类别，[:, -1:]表示取最后一个结果\n",
    "            decoder_inputs = torch.cat([decoder_inputs, next_token], dim=-1) #预测输出拼接到输入中\n",
    "            #(decoder_inputs == self.eos_idx).sum(dim=-1)是判断样本中是否含有EOS标记\n",
    "            #all是每一个都为True，才会结束\n",
    "            if all((decoder_inputs == self.eos_idx).sum(dim=-1) > 0):\n",
    "                break\n",
    "\n",
    "        return TransformerOutput(\n",
    "            preds=decoder_inputs[:, 1:],\n",
    "            logits=logits,\n",
    "            encoder_last_hidden_states=encoder_outputs.last_hidden_states,\n",
    "            encoder_attn_scores=encoder_outputs.attn_scores,\n",
    "            decoder_last_hidden_states=decoder_outputs.last_hidden_states,\n",
    "            decoder_self_attn_scores=decoder_outputs.self_attn_scores,\n",
    "            decoder_cross_attn_scores=decoder_outputs.cross_attn_scores,\n",
    "        )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cd807769457f8925",
   "metadata": {},
   "source": [
    "## 训练模型<br>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eadfba52d66e69a0",
   "metadata": {},
   "source": [
    "### 损失函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "b70d663e2dfd58dd",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:26:55.656823Z",
     "start_time": "2025-03-13T11:26:55.652316Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:40.974995Z",
     "iopub.status.busy": "2025-03-13T12:13:40.974816Z",
     "iopub.status.idle": "2025-03-13T12:13:40.979636Z",
     "shell.execute_reply": "2025-03-13T12:13:40.979140Z",
     "shell.execute_reply.started": "2025-03-13T12:13:40.974977Z"
    }
   },
   "outputs": [],
   "source": [
    "class CrossEntropyWithPadding:\n",
    "    \"\"\"\n",
    "    CrossEntropyWithPadding(label_smoothing=0.1)\n",
    "    label_smoothing: 标签平滑，让模型不要武断地确定输出，而更加关注其他的可能\n",
    "    \"\"\"\n",
    "    def __init__(self, config):\n",
    "        self.label_smoothing = config[\"label_smoothing\"]\n",
    "\n",
    "    def __call__(self, logits, labels, padding_mask=None):\n",
    "        # logits.shape = [batch size, sequence length, num of classes]\n",
    "        # labels.shape = [batch size, sequence length]\n",
    "        # padding_mask.shape = [batch size, sequence length]\n",
    "        bs, seq_len, nc = logits.shape\n",
    "        loss = F.cross_entropy(logits.reshape(bs * seq_len, nc), labels.reshape(-1), reduce=False, label_smoothing=self.label_smoothing) #label_smoothing表示随机将一个类别的概率设置为0.1，使得模型更加关注其他类别\n",
    "        if padding_mask is None:\n",
    "            loss = loss.mean()\n",
    "        else:\n",
    "            padding_mask = 1 - padding_mask.reshape(-1) #将padding_mask reshape成一维张量，mask部分为0，非mask部分为1\n",
    "            loss = torch.mul(loss, padding_mask).sum() / padding_mask.sum()\n",
    "\n",
    "        return loss\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa0f6717cdb29341",
   "metadata": {},
   "source": [
    "### 使用warmup调节学习率\n",
    "使用了Schedule自定义"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "95a6f0f37044cab9",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:27:59.887895Z",
     "start_time": "2025-03-13T11:27:59.780379Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:40.980351Z",
     "iopub.status.busy": "2025-03-13T12:13:40.980176Z",
     "iopub.status.idle": "2025-03-13T12:13:41.084109Z",
     "shell.execute_reply": "2025-03-13T12:13:41.083634Z",
     "shell.execute_reply.started": "2025-03-13T12:13:40.980333Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# NoamDecayScheduler 是一个自定义或外部定义的学习率衰减调度器类。它需要接收配置 config 作为参数，可能实现了特定的学习率衰减方案\n",
    "class NoamDecayScheduler:\n",
    "    def __init__(self, config):\n",
    "        self.d_model = config[\"d_model\"]\n",
    "        self.warmup_steps = config[\"warmup_steps\"]\n",
    "\n",
    "    def __call__(self, step):\n",
    "        step += 1\n",
    "        arg1 = step ** (-0.5) #4000步之后是arg1\n",
    "        arg2 = step * (self.warmup_steps ** (-1.5))  #4000步之前是arg2\n",
    "\n",
    "        arg3 = self.d_model ** (-0.5)\n",
    "\n",
    "        return arg3 * np.minimum(arg1, arg2)\n",
    "\n",
    "\n",
    "temp_learning_rate_schedule = NoamDecayScheduler({\"d_model\": 512, \"warmup_steps\": 4000})\n",
    "#下面是学习率的设计图\n",
    "# 这种设计帮助模型更快收敛\n",
    "plt.plot(temp_learning_rate_schedule(np.arange(0, 40000)))\n",
    "plt.ylabel(\"Leraning rate\")\n",
    "plt.xlabel(\"Train step\")\n",
    "plt.grid()\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8366a9d903ac8a67",
   "metadata": {},
   "source": [
    "### Optimizer<br>\n",
    "使用Adam优化器，学习率衰减使用NoamDecayScheduler"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "c2614cf4c91e752f",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:34:40.755883Z",
     "start_time": "2025-03-13T11:34:40.751575Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:41.084830Z",
     "iopub.status.busy": "2025-03-13T12:13:41.084659Z",
     "iopub.status.idle": "2025-03-13T12:13:41.088693Z",
     "shell.execute_reply": "2025-03-13T12:13:41.088186Z",
     "shell.execute_reply.started": "2025-03-13T12:13:41.084812Z"
    }
   },
   "outputs": [],
   "source": [
    "from torch.optim.lr_scheduler import LambdaLR\n",
    "from torch.optim import Adam\n",
    "\n",
    "def get_optimizer(model, config):\n",
    "    base_lr = 0.1\n",
    "    beta1 = config[\"beta1\"] # Adam 的 beta1\n",
    "    beta2 = config[\"beta2\"] # Adam 的 beta2\n",
    "    eps = config[\"eps\"]\n",
    "    optimizer = Adam(model.parameters(), lr=base_lr, betas=(beta1, beta2), eps=eps)\n",
    "    lr_scheduler = NoamDecayScheduler(config) #config是一个字典，包含了学习率衰减的参数\n",
    "    # 使用 LambdaLR 调度器，它可以根据给定的函数 lr_lambda 调整学习率。这里将 lr_scheduler 作为函数传递给 LambdaLR，它包含了特定于模型或任务的学习率调度规则\n",
    "    scheduler = LambdaLR(optimizer, lr_lambda=lr_scheduler)\n",
    "    return optimizer, scheduler"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca2dba0732b08f74",
   "metadata": {},
   "source": [
    "### Callbacks<br>\n",
    "方便使用TensorBoard进行可视化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "4e56b77cf327f805",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:30:12.954572Z",
     "start_time": "2025-03-13T11:29:57.277102Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:41.089470Z",
     "iopub.status.busy": "2025-03-13T12:13:41.089290Z",
     "iopub.status.idle": "2025-03-13T12:13:41.145753Z",
     "shell.execute_reply": "2025-03-13T12:13:41.145303Z",
     "shell.execute_reply.started": "2025-03-13T12:13:41.089451Z"
    }
   },
   "outputs": [],
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "\n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\",\n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "            )\n",
    "\n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "\n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "\n",
    "        )\n",
    "\n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d81138c5cb6ff023",
   "metadata": {},
   "source": [
    "### SaveBestModel<br>\n",
    "保存最佳模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "bd78247feca524d3",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:30:16.823110Z",
     "start_time": "2025-03-13T11:30:16.817716Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:41.146538Z",
     "iopub.status.busy": "2025-03-13T12:13:41.146280Z",
     "iopub.status.idle": "2025-03-13T12:13:41.151327Z",
     "shell.execute_reply": "2025-03-13T12:13:41.150891Z",
     "shell.execute_reply.started": "2025-03-13T12:13:41.146518Z"
    }
   },
   "outputs": [],
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch.\n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = - np.inf\n",
    "\n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "\n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "\n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4ee0120f2eb2149",
   "metadata": {},
   "source": [
    "### EarlyStopping<br>\n",
    "早停机制，当验证集损失不再下降时，停止训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "3a02e15c2ac0a914",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:30:43.448514Z",
     "start_time": "2025-03-13T11:30:43.444Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:41.152096Z",
     "iopub.status.busy": "2025-03-13T12:13:41.151929Z",
     "iopub.status.idle": "2025-03-13T12:13:41.156051Z",
     "shell.execute_reply": "2025-03-13T12:13:41.155608Z",
     "shell.execute_reply.started": "2025-03-13T12:13:41.152079Z"
    }
   },
   "outputs": [],
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute\n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = - np.inf\n",
    "        self.counter = 0\n",
    "\n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter\n",
    "            self.counter = 0\n",
    "        else:\n",
    "            self.counter += 1\n",
    "\n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e1f2dd03dbc06",
   "metadata": {},
   "source": [
    "### 训练模型<br>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bb0ccbfabd198865",
   "metadata": {},
   "source": [
    "### 调节超参数<br>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "e7ecf55ef0bb80aa",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:33:14.548215Z",
     "start_time": "2025-03-13T11:33:14.423144Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:41.156815Z",
     "iopub.status.busy": "2025-03-13T12:13:41.156545Z",
     "iopub.status.idle": "2025-03-13T12:13:41.298548Z",
     "shell.execute_reply": "2025-03-13T12:13:41.298020Z",
     "shell.execute_reply.started": "2025-03-13T12:13:41.156797Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "save cache to wmt16/.cache/de2en_train_128.npy\n",
      "save cache to wmt16/.cache/de2en_val_128.npy\n"
     ]
    }
   ],
   "source": [
    "#模型的超参\n",
    "config = {\n",
    "    \"bos_idx\": 1,   # 开始标记\n",
    "    \"eos_idx\": 3,   # 结束标记\n",
    "    \"pad_idx\": 0,   # 填充标记\n",
    "    \"vocab_size\": len(word2idx),         # 词表大小\n",
    "    \"max_length\": 128,  # 句子最大长度\n",
    "    \"d_model\": 512,#可以调整\n",
    "    \"dim_feedforward\": 2048, # FFN 的隐藏层大小\n",
    "    \"dropout\": 0.1,#可以调整\n",
    "    \"layer_norm_eps\": 1e-6, # 层归一化的 epsilon, 防止除零错误\n",
    "    \"num_heads\": 8,#论文里是8，可以调整\n",
    "    \"num_decoder_layers\": 2, #论文是6，可以调整\n",
    "    \"num_encoder_layers\": 2, #论文是6，可以调整\n",
    "    \"label_smoothing\": 0.1, # 标签平滑，让模型不要武断地确定输出，而更加关注其他的可能\n",
    "    \"beta1\": 0.9, # Adam 的 beta1\n",
    "    \"beta2\": 0.98,  # Adam 的 beta2\n",
    "    \"eps\": 1e-9, # Adam 的 epsilon\n",
    "    \"warmup_steps\": 4000,   # warmup 步数\n",
    "    \"share_embedding\": False, # 是否共享词向量，如果改为True，效果不好\n",
    "    }\n",
    "\n",
    "\n",
    "def get_dl(dataset, batch_size, shuffle=True):\n",
    "    \"\"\"\n",
    "    Get dataloader.\n",
    "    :param dataset:     Dataset\n",
    "    :param batch_size:  batch size\n",
    "    :param shuffle:     shuffle or not\n",
    "    :return:            DataLoader\n",
    "    \"\"\"\n",
    "    sampler = TransformerBatchSampler(dataset, batch_size=batch_size, shuffle_batch=shuffle)\n",
    "    sample_dl = DataLoader(dataset, batch_sampler=sampler, collate_fn=partial(collate_fct, tokenizer=tokenizer))\n",
    "    return sample_dl\n",
    "\n",
    "# dataset\n",
    "train_ds = LangPairDataset(\"train\", max_length=config[\"max_length\"])\n",
    "val_ds = LangPairDataset(\"val\", max_length=config[\"max_length\"])\n",
    "# tokenizer\n",
    "tokenizer = Tokenizer(word2idx=word2idx, idx2word=idx2word, max_length=config[\"max_length\"])\n",
    "batch_size = 2048\n",
    "# dataloader\n",
    "train_dl = get_dl(train_ds, batch_size=batch_size, shuffle=True)\n",
    "val_dl = get_dl(val_ds, batch_size=batch_size, shuffle=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "b0bf198e21127fc1",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:33:23.789668Z",
     "start_time": "2025-03-13T11:33:23.784728Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:41.299338Z",
     "iopub.status.busy": "2025-03-13T12:13:41.299107Z",
     "iopub.status.idle": "2025-03-13T12:13:41.303492Z",
     "shell.execute_reply": "2025-03-13T12:13:41.302969Z",
     "shell.execute_reply.started": "2025-03-13T12:13:41.299318Z"
    }
   },
   "outputs": [],
   "source": [
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    for batch in dataloader:\n",
    "        encoder_inputs = batch[\"encoder_inputs\"]\n",
    "        encoder_inputs_mask = batch[\"encoder_inputs_mask\"]\n",
    "        decoder_inputs = batch[\"decoder_inputs\"]\n",
    "        decoder_labels = batch[\"decoder_labels\"]\n",
    "        decoder_labels_mask = batch[\"decoder_labels_mask\"]\n",
    "\n",
    "        # 前向计算\n",
    "        outputs = model(\n",
    "            encoder_inputs=encoder_inputs,\n",
    "            decoder_inputs=decoder_inputs,\n",
    "            encoder_inputs_mask=encoder_inputs_mask\n",
    "            )\n",
    "        logits = outputs.logits\n",
    "        loss = loss_fct(logits, decoder_labels, padding_mask=decoder_labels_mask)         # 验证集损失\n",
    "        loss_list.append(loss.cpu().item())\n",
    "\n",
    "    return np.mean(loss_list)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "9ecf4320313117a2",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:34:18.082983Z",
     "start_time": "2025-03-13T11:34:18.075583Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:41.304520Z",
     "iopub.status.busy": "2025-03-13T12:13:41.304081Z",
     "iopub.status.idle": "2025-03-13T12:13:41.313155Z",
     "shell.execute_reply": "2025-03-13T12:13:41.312677Z",
     "shell.execute_reply.started": "2025-03-13T12:13:41.304497Z"
    }
   },
   "outputs": [],
   "source": [
    "# 训练\n",
    "def training(\n",
    "    model,\n",
    "    train_loader,\n",
    "    val_loader,\n",
    "    epoch,\n",
    "    loss_fct,\n",
    "    optimizer,\n",
    "    scheduler=None,\n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=None,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500,\n",
    "    ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "\n",
    "    global_step = 1\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for batch in train_loader:\n",
    "                encoder_inputs = batch[\"encoder_inputs\"]\n",
    "                encoder_inputs_mask = batch[\"encoder_inputs_mask\"]\n",
    "                decoder_inputs = batch[\"decoder_inputs\"]\n",
    "                decoder_labels = batch[\"decoder_labels\"]\n",
    "                decoder_labels_mask = batch[\"decoder_labels_mask\"]\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "\n",
    "                # 前向计算\n",
    "                outputs = model(\n",
    "                    encoder_inputs=encoder_inputs,\n",
    "                    decoder_inputs=decoder_inputs,\n",
    "                    encoder_inputs_mask=encoder_inputs_mask\n",
    "                    )\n",
    "                logits = outputs.logits\n",
    "                loss = loss_fct(logits, decoder_labels, padding_mask=decoder_labels_mask)\n",
    "\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                if scheduler is not None:\n",
    "                    scheduler.step() # 更新学习率\n",
    "\n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"step\": global_step\n",
    "                })\n",
    "\n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "\n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    cur_lr = optimizer.param_groups[0][\"lr\"] if scheduler is None else scheduler.get_last_lr()[0]\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step,\n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            lr=cur_lr,\n",
    "                            )\n",
    "\n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=-val_loss)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(-val_loss)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "\n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "            pbar.set_postfix({\"epoch\": epoch_id, \"loss\": loss, \"val_loss\": val_loss})\n",
    "\n",
    "    return record_dict\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "fdae620264ba765b",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:35:01.002752Z",
     "start_time": "2025-03-13T11:34:59.737612Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:41.314085Z",
     "iopub.status.busy": "2025-03-13T12:13:41.313707Z",
     "iopub.status.idle": "2025-03-13T12:13:41.868826Z",
     "shell.execute_reply": "2025-03-13T12:13:41.868291Z",
     "shell.execute_reply.started": "2025-03-13T12:13:41.314062Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "模型参数量: 42537151\n"
     ]
    }
   ],
   "source": [
    "#计算模型参数量\n",
    "model = TransformerModel(config)\n",
    "print(f\"模型参数量: {sum(p.numel() for p in model.parameters() if p.requires_grad)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "f9796e1982ffda63",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-03-13T12:13:41.869779Z",
     "iopub.status.busy": "2025-03-13T12:13:41.869503Z",
     "iopub.status.idle": "2025-03-13T12:20:08.315763Z",
     "shell.execute_reply": "2025-03-13T12:20:08.315247Z",
     "shell.execute_reply.started": "2025-03-13T12:13:41.869759Z"
    },
    "scrolled": true,
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  0%|          | 0/280 [00:00<?, ?it/s]/usr/local/lib/python3.10/site-packages/torch/nn/_reduction.py:51: UserWarning: size_average and reduce args will be deprecated, please use reduction='none' instead.\n",
      "  warnings.warn(warning.format(ret))\n",
      "20840it [06:25, 54.12it/s, epoch=19, loss=2.49, val_loss=3.04]\n"
     ]
    }
   ],
   "source": [
    "epoch = 20\n",
    "\n",
    "# model\n",
    "model = TransformerModel(config)\n",
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = CrossEntropyWithPadding(config)\n",
    "# 2. 定义优化器 采用 adam\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer, scheduler = get_optimizer(model, config)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "exp_name = \"translate-transformer-{}\".format(\"share\" if config[\"share_embedding\"] else \"not-share\")\n",
    "tensorboard_callback = TensorBoardCallback(f\"runs/{exp_name}\")\n",
    "# tensorboard_callback.draw_model(model, [1, MAX_LENGTH])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(\n",
    "    f\"checkpoints/{exp_name}\", save_step=500, save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=8)\n",
    "\n",
    "model = model.to(device)\n",
    "\n",
    "record = training(\n",
    "    model,\n",
    "    train_dl,\n",
    "    val_dl,\n",
    "    epoch,\n",
    "    loss_fct,\n",
    "    optimizer,\n",
    "    scheduler,\n",
    "    tensorboard_callback=tensorboard_callback,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500\n",
    "    )\n",
    "\n",
    "# Training took 3.5 days on 8 P100 GPUs\n",
    "# We trained the base models for a total of 100,000 steps or 12 hours. For our big models,(described on the bottom line of table 3), step time was 1.0 seconds. The big models were trained for 300,000 steps (3.5 days)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b29738601e08e5c",
   "metadata": {},
   "source": [
    "## 推理和预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "7b28617547da5095",
   "metadata": {
    "ExecutionIndicator": {
     "show": true
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:20:08.316856Z",
     "iopub.status.busy": "2025-03-13T12:20:08.316416Z",
     "iopub.status.idle": "2025-03-13T12:20:20.986298Z",
     "shell.execute_reply": "2025-03-13T12:20:20.985635Z",
     "shell.execute_reply.started": "2025-03-13T12:20:08.316834Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://mirrors.cloud.aliyuncs.com/pypi/simple\n",
      "Requirement already satisfied: Cython in /usr/local/lib/python3.10/site-packages (3.0.12)\n",
      "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001B[0m\u001B[33m\n",
      "\u001B[0m\n",
      "\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m A new release of pip is available: \u001B[0m\u001B[31;49m23.3.2\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m25.0.1\u001B[0m\n",
      "\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m To update, run: \u001B[0m\u001B[32;49mpip install --upgrade pip\u001B[0m\n",
      "Looking in indexes: https://mirrors.cloud.aliyuncs.com/pypi/simple\n",
      "Requirement already satisfied: fastBPE in /usr/local/lib/python3.10/site-packages (0.1.0)\n",
      "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001B[0m\u001B[33m\n",
      "\u001B[0m\n",
      "\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m A new release of pip is available: \u001B[0m\u001B[31;49m23.3.2\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m25.0.1\u001B[0m\n",
      "\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m To update, run: \u001B[0m\u001B[32;49mpip install --upgrade pip\u001B[0m\n",
      "Looking in indexes: https://mirrors.cloud.aliyuncs.com/pypi/simple\n",
      "Requirement already satisfied: sacremoses in /usr/local/lib/python3.10/site-packages (0.1.1)\n",
      "Requirement already satisfied: regex in /usr/local/lib/python3.10/site-packages (from sacremoses) (2024.11.6)\n",
      "Requirement already satisfied: click in /usr/local/lib/python3.10/site-packages (from sacremoses) (8.1.8)\n",
      "Requirement already satisfied: joblib in /usr/local/lib/python3.10/site-packages (from sacremoses) (1.4.2)\n",
      "Requirement already satisfied: tqdm in /usr/local/lib/python3.10/site-packages (from sacremoses) (4.67.1)\n",
      "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001B[0m\u001B[33m\n",
      "\u001B[0m\n",
      "\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m A new release of pip is available: \u001B[0m\u001B[31;49m23.3.2\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m25.0.1\u001B[0m\n",
      "\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m To update, run: \u001B[0m\u001B[32;49mpip install --upgrade pip\u001B[0m\n"
     ]
    }
   ],
   "source": [
    "!pip install Cython  # if failed to install fastBPE, try this line\n",
    "!pip install fastBPE #分词使用\n",
    "!pip install sacremoses\n",
    "# 在 Windows 系统上并没有 sys/mman.h 文件\n",
    "# 这里由于代码提交至阿里云，所以注释掉第一条"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "2191165e6d557231",
   "metadata": {
    "ExecutionIndicator": {
     "show": true
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:20:20.987484Z",
     "iopub.status.busy": "2025-03-13T12:20:20.987192Z",
     "iopub.status.idle": "2025-03-13T12:20:21.062386Z",
     "shell.execute_reply": "2025-03-13T12:20:21.061876Z",
     "shell.execute_reply.started": "2025-03-13T12:20:20.987461Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_1007/2203663124.py:3: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n",
      "  state_dict = torch.load(f\"./models/transformer-de-en/best.ckpt\", map_location=\"cpu\")\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "# state_dict是保存的模型，可以直接加载\n",
    "state_dict = torch.load(f\"./models/transformer-de-en/best.ckpt\", map_location=\"cpu\")\n",
    "\n",
    "# state_dict1 = torch.load(\"epoch125-step132426.ckpt\", map_location=\"cpu\")\n",
    "# state_dict = state_dict1[\"state_dict\"]\n",
    "\n",
    "# update keys by dropping `model`\n",
    "# for key in list(state_dict):\n",
    "#     state_dict[key.replace(\"model.\", \"\")] = state_dict.pop(key)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "5d574bb5b8f856ec",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:38:26.872725Z",
     "start_time": "2025-03-13T11:38:26.808041Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:20:21.063481Z",
     "iopub.status.busy": "2025-03-13T12:20:21.063064Z",
     "iopub.status.idle": "2025-03-13T12:20:21.193529Z",
     "shell.execute_reply": "2025-03-13T12:20:21.192912Z",
     "shell.execute_reply.started": "2025-03-13T12:20:21.063460Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "!rm -r wmt16/.cache"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "518308b7fc329f64",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-13T11:38:27.496239Z",
     "start_time": "2025-03-13T11:38:27.492793Z"
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:26:50.681787Z",
     "iopub.status.busy": "2025-03-13T12:26:50.681417Z",
     "iopub.status.idle": "2025-03-13T12:26:50.686063Z",
     "shell.execute_reply": "2025-03-13T12:26:50.685559Z",
     "shell.execute_reply.started": "2025-03-13T12:26:50.681764Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['a man in an seinem hat sh-@@ at guitar .']"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 测试decoder部分\n",
    "tokenizer.decode([[   5,   16,    6,   23,  150,   80, 8248,   35,  232,    4,    3]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "2a8e3a7d17ff8b87",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-03-13T12:20:21.199499Z",
     "iopub.status.busy": "2025-03-13T12:20:21.199273Z",
     "iopub.status.idle": "2025-03-13T12:20:26.024402Z",
     "shell.execute_reply": "2025-03-13T12:20:26.023792Z",
     "shell.execute_reply.started": "2025-03-13T12:20:21.199480Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "save cache to wmt16/.cache/de2en_test_128.npy\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "0it [00:00, ?it/s]/usr/local/lib/python3.10/site-packages/nltk/translate/bleu_score.py:577: UserWarning: \n",
      "The hypothesis contains 0 counts of 4-gram overlaps.\n",
      "Therefore the BLEU score evaluates to 0, independently of\n",
      "how many N-gram overlaps of lower order it contains.\n",
      "Consider using lower n-gram order or use SmoothingFunction()\n",
      "  warnings.warn(_msg)\n",
      "/usr/local/lib/python3.10/site-packages/nltk/translate/bleu_score.py:577: UserWarning: \n",
      "The hypothesis contains 0 counts of 3-gram overlaps.\n",
      "Therefore the BLEU score evaluates to 0, independently of\n",
      "how many N-gram overlaps of lower order it contains.\n",
      "Consider using lower n-gram order or use SmoothingFunction()\n",
      "  warnings.warn(_msg)\n",
      "22it [00:00, 214.96it/s]/usr/local/lib/python3.10/site-packages/nltk/translate/bleu_score.py:577: UserWarning: \n",
      "The hypothesis contains 0 counts of 2-gram overlaps.\n",
      "Therefore the BLEU score evaluates to 0, independently of\n",
      "how many N-gram overlaps of lower order it contains.\n",
      "Consider using lower n-gram order or use SmoothingFunction()\n",
      "  warnings.warn(_msg)\n",
      "966it [00:03, 247.31it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "testing loss: 2.974758107593094\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.6762964214150887"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 准备计算BLEU1分数\n",
    "from nltk.translate.bleu_score import sentence_bleu\n",
    "# load checkpoints\n",
    "model = TransformerModel(config)\n",
    "model.load_state_dict(state_dict)\n",
    "\n",
    "loss_fct = CrossEntropyWithPadding(config)\n",
    "# from dataset import LangPairDataset\n",
    "test_ds = LangPairDataset(\"test\", max_length=128, data_dir=\"./wmt16\")\n",
    "test_dl = DataLoader(test_ds, batch_size=1, collate_fn=partial(collate_fct, tokenizer=tokenizer))\n",
    "\n",
    "model = model.to(device)\n",
    "model.eval()\n",
    "collect = {}\n",
    "loss_collect = []\n",
    "\n",
    "predictions = []\n",
    "answers = []\n",
    "# 初始化BLEU分数列表\n",
    "bleu_scores = []\n",
    "for idx, batch in tqdm(enumerate(test_dl)):\n",
    "    encoder_inputs = batch[\"encoder_inputs\"]\n",
    "    encoder_inputs_mask = batch[\"encoder_inputs_mask\"]\n",
    "    decoder_inputs = batch[\"decoder_inputs\"]\n",
    "    decoder_labels = batch[\"decoder_labels\"]\n",
    "    # print(decoder_labels.cpu())\n",
    "    # decoder_labels1=tokenizer.decode(decoder_labels.cpu().numpy())\n",
    "    # print(decoder_labels1)\n",
    "    # 前向计算\n",
    "    outputs = model(\n",
    "        encoder_inputs=encoder_inputs,\n",
    "        decoder_inputs=decoder_inputs,\n",
    "        encoder_inputs_mask=encoder_inputs_mask\n",
    "        )\n",
    "    loss = loss_fct(outputs.logits, decoder_labels)         # 测试集损失，如果batch_size不为1，需要加入mask\n",
    "\n",
    "    # print(outputs.logits.shape, decoder_labels.shape)\n",
    "\n",
    "    # loss = loss_fct(outputs.logits[:, :decoder_labels.shape[1]], decoder_labels)         # 验证集损失\n",
    "    # outputs = model.infer(encoder_inputs=encoder_inputs)\n",
    "    # print(outputs.logits.shape)\n",
    "    preds = outputs.logits.argmax(dim=-1) # 预测结果，[1,seq_len]\n",
    "    # print(preds.shape)\n",
    "    #把preds转为英文单词\n",
    "    preds = tokenizer.decode(preds.cpu().numpy()) #['预测句子']\n",
    "    # predictions.append(preds)\n",
    "    # print(preds)\n",
    "    #把decoder_labels转为英文单词\n",
    "    decoder_labels = tokenizer.decode(decoder_labels.cpu().numpy()) #['标签句子']\n",
    "    # answers.append(decoder_labels)\n",
    "    # print(decoder_labels)\n",
    "    belu=sentence_bleu([decoder_labels[0].split()],preds[0].split(),weights=(1, 0, 0, 0))\n",
    "    bleu_scores.append(belu)\n",
    "    collect[idx] = {\"loss\": loss.item(), \"src_inputs\": encoder_inputs, \"trg_inputs\": decoder_inputs, \"mask\": encoder_inputs_mask, \"trg_labels\": decoder_labels, \"preds\": preds}\n",
    "    loss_collect.append(loss.item())\n",
    "    # break\n",
    "\n",
    "# sort collect by value\n",
    "collect = sorted(collect.items(), key=lambda x: x[1][\"loss\"])\n",
    "print(f\"testing loss: {np.array(loss_collect).mean()}\")\n",
    "sum(bleu_scores) / len(bleu_scores)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "7bc6279d4ae6e5be",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-03-13T12:20:26.025884Z",
     "iopub.status.busy": "2025-03-13T12:20:26.025218Z",
     "iopub.status.idle": "2025-03-13T12:20:30.486348Z",
     "shell.execute_reply": "2025-03-13T12:20:30.485878Z",
     "shell.execute_reply.started": "2025-03-13T12:20:26.025843Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "load test dataset from wmt16/.cache/de2en_test_128.npy\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "966it [00:03, 249.97it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "testing loss: 2.974758107593094\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.30462208229999677"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 准备计算BLEU4分数\n",
    "from nltk.translate.bleu_score import sentence_bleu\n",
    "# load checkpoints\n",
    "model = TransformerModel(config)\n",
    "model.load_state_dict(state_dict)\n",
    "\n",
    "loss_fct = CrossEntropyWithPadding(config)\n",
    "# from dataset import LangPairDataset\n",
    "test_ds = LangPairDataset(\"test\", max_length=128, data_dir=\"./wmt16\")\n",
    "test_dl = DataLoader(test_ds, batch_size=1, collate_fn=partial(collate_fct, tokenizer=tokenizer))\n",
    "\n",
    "model = model.to(device)\n",
    "model.eval()\n",
    "collect = {}\n",
    "loss_collect = []\n",
    "\n",
    "predictions = []\n",
    "answers = []\n",
    "# 初始化BLEU分数列表\n",
    "bleu_scores = []\n",
    "for idx, batch in tqdm(enumerate(test_dl)):\n",
    "    encoder_inputs = batch[\"encoder_inputs\"]\n",
    "    encoder_inputs_mask = batch[\"encoder_inputs_mask\"]\n",
    "    decoder_inputs = batch[\"decoder_inputs\"]\n",
    "    decoder_labels = batch[\"decoder_labels\"]\n",
    "    # print(decoder_labels.cpu())\n",
    "    # decoder_labels1=tokenizer.decode(decoder_labels.cpu().numpy())\n",
    "    # print(decoder_labels1)\n",
    "    # 前向计算\n",
    "    outputs = model(\n",
    "        encoder_inputs=encoder_inputs,\n",
    "        decoder_inputs=decoder_inputs,\n",
    "        encoder_inputs_mask=encoder_inputs_mask\n",
    "        )\n",
    "    loss = loss_fct(outputs.logits, decoder_labels)         # 测试集损失，如果batch_size不为1，需要加入mask\n",
    "\n",
    "    # print(outputs.logits.shape, decoder_labels.shape)\n",
    "\n",
    "    # loss = loss_fct(outputs.logits[:, :decoder_labels.shape[1]], decoder_labels)         # 验证集损失\n",
    "    # outputs = model.infer(encoder_inputs=encoder_inputs)\n",
    "    # print(outputs.logits.shape)\n",
    "    preds = outputs.logits.argmax(dim=-1) # 预测结果，[1,seq_len]\n",
    "    # print(preds.shape)\n",
    "    #把preds转为英文单词\n",
    "    preds = tokenizer.decode(preds.cpu().numpy()) #['预测句子']\n",
    "    # predictions.append(preds)\n",
    "    # print(preds)\n",
    "    #把decoder_labels转为英文单词\n",
    "    decoder_labels = tokenizer.decode(decoder_labels.cpu().numpy()) #['标签句子']\n",
    "    # answers.append(decoder_labels)\n",
    "    # print(decoder_labels)\n",
    "    belu=sentence_bleu([decoder_labels[0].split()],preds[0].split(),weights=(0.25, 0.25, 0.25, 0.25))\n",
    "    bleu_scores.append(belu)\n",
    "    collect[idx] = {\"loss\": loss.item(), \"src_inputs\": encoder_inputs, \"trg_inputs\": decoder_inputs, \"mask\": encoder_inputs_mask, \"trg_labels\": decoder_labels, \"preds\": preds}\n",
    "    loss_collect.append(loss.item())\n",
    "    # break\n",
    "\n",
    "# sort collect by value\n",
    "collect = sorted(collect.items(), key=lambda x: x[1][\"loss\"])\n",
    "print(f\"testing loss: {np.array(loss_collect).mean()}\")\n",
    "sum(bleu_scores) / len(bleu_scores)"
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "BLEU-1分数：0.6762<br>\n",
    "BLEU-4分数：0.3046<br>\n",
    "测试集损失：2.97<br>\n",
    "总的来说，训练效果还不错"
   ],
   "id": "5dfbe1217c1a8730"
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "893dc42507ce2c42",
   "metadata": {
    "ExecutionIndicator": {
     "show": true
    },
    "execution": {
     "iopub.execute_input": "2025-03-13T12:35:10.437275Z",
     "iopub.status.busy": "2025-03-13T12:35:10.436871Z",
     "iopub.status.idle": "2025-03-13T12:35:10.456566Z",
     "shell.execute_reply": "2025-03-13T12:35:10.455955Z",
     "shell.execute_reply.started": "2025-03-13T12:35:10.437251Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "import re\n",
    "from fastBPE import fastBPE\n",
    "from sacremoses import MosesDetokenizer, MosesTokenizer\n",
    "\n",
    "# `MosesTokenizer` 和 `MosesDetokenizer` 是来自 `sacremoses` 库的工具，用于自然语言处理中的分词（Tokenization）和去标记化（Detokenization）。这些工具主要用于对文本进行预处理和后处理，通常在处理自然语言处理任务时会用到。\n",
    "#\n",
    "# ### MosesTokenizer：\n",
    "# - **作用**：将原始文本分割成单词和标点符号。\n",
    "# - **特点**：基于 Moses 翻译工具中使用的分词方法。\n",
    "# - **功能**：\n",
    "#   - 将句子分割成单词和标点符号。\n",
    "#   - 处理缩写、连字符、标点等特殊情况。\n",
    "#   - 对文本进行标记化，方便后续处理。\n",
    "#\n",
    "# ### MosesDetokenizer：\n",
    "# - **作用**：将分词后的文本重新组合成原始的句子。\n",
    "# - **特点**：用于对分词后的文本进行还原，使其恢复为可读的句子形式。\n",
    "# - **功能**：\n",
    "#   - 将分词后的单词和标点符号重新组合成句子。\n",
    "#   - 处理分词后的标点、缩写等情况，使得结果更加自然和可读。\n",
    "#\n",
    "# 这些工具通常在文本预处理和后处理过程中使用，对输入的文本进行标记化和去标记化，是一种常用的处理方式。在自然语言处理任务中，对文本进行正确的分词和还原是很重要的，而 `MosesTokenizer` 和 `MosesDetokenizer` 提供了方便、高效的工具来处理这些任务。\n",
    "\n",
    "class Translator:\n",
    "    def __init__(self, model, src_tokenizer, trg_tokenizer):\n",
    "        self.bpe = fastBPE(\"./wmt16/bpe.20000\", \"./wmt16/vocab\")\n",
    "        self.mose_tokenizer = MosesTokenizer(lang=\"de\")\n",
    "        self.mose_detokenizer = MosesDetokenizer(lang=\"en\")\n",
    "        self.model = model\n",
    "        self.model.eval()\n",
    "        self.src_tokenizer = src_tokenizer\n",
    "        self.trg_tokenizer = trg_tokenizer\n",
    "        self.pattern = re.compile(r'(@@ )|(@@ ?$)')\n",
    "\n",
    "    def draw_attention_map(self, attn_scores, cross_attn_scores, src_words_list, trg_words_list):\n",
    "        \"\"\"绘制注意力热力图\n",
    "        attn_scores (numpy.ndarray): 表示自注意力机制（self-attention）分数。\n",
    "        cross_attn_scores (numpy.ndarray): 表示交叉注意力机制的注意力分数。\n",
    "        src_words_list (list): 源语言句子的单词列表。\n",
    "        trg_words_list (list): 目标语言句子的单词列表。\n",
    "        \"\"\"\n",
    "        assert len(attn_scores.shape) == 3, \"attn_scores shape should be \" \\\n",
    "            f\"[num heads, target sequence length, target sequence length], but got {attn_scores.shape}\"\n",
    "        attn_scores = attn_scores[:, :len(trg_words_list), :len(trg_words_list)]\n",
    "\n",
    "        assert len(cross_attn_scores.shape) == 3, \"attn_scores shape should be \" \\\n",
    "            f\"[num heads, target sequence length, source sequence length], but got {cross_attn_scores.shape}\"\n",
    "        cross_attn_scores = cross_attn_scores[:, :len(trg_words_list), :len(src_words_list)]\n",
    "\n",
    "        num_heads, trg_len, src_len = cross_attn_scores.shape\n",
    "\n",
    "        fig = plt.figure(figsize=(10, 5), constrained_layout=True) # constrained_layout=True 自动调整子图参数，使之填充整个图像区域\n",
    "        grid = plt.GridSpec(trg_len, trg_len + src_len, wspace=0.1, hspace=0.1)# wspace,hspace 控制子图之间的间距\n",
    "        #下面是attn_scores的热力图\n",
    "        self_map = fig.add_subplot(grid[:,:trg_len]) #  添加子图\n",
    "        self_map.matshow(attn_scores.mean(dim=0), cmap='viridis') # 绘制热力图，cmap表示颜色,dim=0表示对第0维求均值\n",
    "        self_map.set_yticks(range(trg_len), trg_words_list, fontsize=10)\n",
    "        self_map.set_xticks(range(trg_len), [\"[BOS]\"] + trg_words_list[:-1], rotation=90)\n",
    "        #下面是cross_attn_scores的热力图\n",
    "        cross_map = fig.add_subplot(grid[:, trg_len:])\n",
    "        cross_map.matshow(cross_attn_scores.mean(dim=0), cmap='viridis')\n",
    "        cross_map.set_yticks(range(trg_len), [], fontsize=6)\n",
    "        cross_map.set_xticks(range(src_len), src_words_list, rotation=90)\n",
    "\n",
    "        plt.show()\n",
    "\n",
    "    def draw_attention_maps(self, attn_scores, cross_attn_scores, src_words_list, trg_words_list, heads_list):\n",
    "        \"\"\"绘制注意力热力图\n",
    "\n",
    "        Args:\n",
    "            - scores (numpy.ndarray): shape = [source sequence length, target sequence length]\n",
    "        \"\"\"\n",
    "        assert len(attn_scores.shape) == 3, \"attn_scores shape should be \" \\\n",
    "            f\"[num heads, target sequence length, target sequence length], but got {attn_scores.shape}\"\n",
    "        attn_scores = attn_scores[:, :len(trg_words_list), :len(trg_words_list)]\n",
    "\n",
    "        assert len(cross_attn_scores.shape) == 3, \"attn_scores shape should be \" \\\n",
    "            f\"[num heads, target sequence length, source sequence length], but got {cross_attn_scores.shape}\"\n",
    "        cross_attn_scores = cross_attn_scores[:, :len(trg_words_list), :len(src_words_list)]\n",
    "        # cross_attn_scores = cross_attn_scores[:, :len(src_words_list), :len(src_words_list)]\n",
    "\n",
    "        num_heads, trg_len, src_len = cross_attn_scores.shape\n",
    "        fig, axes = plt.subplots(2, len(heads_list), figsize=(6 * len(heads_list), 12))  # 增加宽度\n",
    "        plt.subplots_adjust(right=0.85)  # 为colorbar留出空间\n",
    "\n",
    "        for i, heads_idx in enumerate(heads_list):\n",
    "            # 自注意力部分\n",
    "            im1 = axes[0, i].matshow(attn_scores[heads_idx], cmap='coolwarm', vmin=0, vmax=1)\n",
    "\n",
    "            # 添加数值\n",
    "            for (x, y), val in np.ndenumerate(attn_scores[heads_idx]):\n",
    "                axes[0, i].text(x, y, f\"{val:.2f}\", ha='center', va='center', \n",
    "                               color='white' if val > 0.5 else 'black', fontsize=8)\n",
    "\n",
    "            axes[0, i].set_title(f\"Self-Attn Head {heads_idx}\")\n",
    "\n",
    "            # 跨注意力部分\n",
    "            im2 = axes[1, i].matshow(cross_attn_scores[heads_idx], cmap='coolwarm', vmin=0, vmax=1)\n",
    "\n",
    "            # 添加颜色条\n",
    "            cax1 = fig.add_axes([0.9, 0.55 - i*0.4, 0.02, 0.3])  # 调整colorbar位置\n",
    "            fig.colorbar(im1, cax=cax1)\n",
    "\n",
    "            cax2 = fig.add_axes([0.9, 0.15 - i*0.4, 0.02, 0.3])\n",
    "            fig.colorbar(im2, cax=cax2)\n",
    "\n",
    "        plt.tight_layout()  # 解决布局警告\n",
    "        plt.show()\n",
    "\n",
    "\n",
    "    def __call__(self, sentence_list, heads_list=None, layer_idx=-1):\n",
    "        # 将输入句子列表转换为小写，并使用 MosesTokenizer 进行分词处理。\n",
    "        sentence_list = [\" \".join(self.mose_tokenizer.tokenize(s.lower())) for s in sentence_list]\n",
    "        # 将分词后的结果进行 BPE 编码，得到 tokens_list。\n",
    "        tokens_list = [s.split() for s in self.bpe.apply(sentence_list)]\n",
    "        # 使用 src_tokenizer 对 tokens_list 进行编码，同时添加起始标记 ([BOS]) 和结束标记 ([EOS])。\n",
    "        encoder_input, attn_mask = self.src_tokenizer.encode(\n",
    "            tokens_list,\n",
    "            add_bos=True,\n",
    "            add_eos=True,\n",
    "            return_mask=True,\n",
    "            )\n",
    "        encoder_input = torch.Tensor(encoder_input).to(dtype=torch.int64)\n",
    "        # 使用模型的 infer 方法对编码器输入进行推理，得到输出结果 outputs\n",
    "        outputs = model.infer(encoder_inputs=encoder_input, encoder_inputs_mask=attn_mask)\n",
    "\n",
    "        preds = outputs.preds.numpy()\n",
    "        # 使用目标语言的 trg_tokenizer 对预测序列进行解码，得到解码后的目标语言句子列表 trg_decoded。\n",
    "        trg_decoded = self.trg_tokenizer.decode(preds, split=True, remove_eos=False, remove_bos=False, remove_pad=False)\n",
    "        # 使用源语言的 src_tokenizer 对编码器输入进行解码，得到解码后的源语言句子列表 src_decoded。为下面绘制热力图做准备。\n",
    "        src_decoded = self.src_tokenizer.decode(\n",
    "            encoder_input.numpy(),\n",
    "            split=True,\n",
    "            remove_bos=False,\n",
    "            remove_eos=False\n",
    "            )\n",
    "\n",
    "        # post processed attn scores\n",
    "        # outputs.decoder_attentions[-1]  # the last layer of self-attention scores\n",
    "\n",
    "        # draw the attention map of the last decoder block\n",
    "        for attn_score, cross_attn_score, src, trg in zip(\n",
    "            outputs.decoder_self_attn_scores[layer_idx], outputs.decoder_cross_attn_scores[layer_idx], src_decoded, trg_decoded):\n",
    "            if heads_list is None:# 如果没有指定heads_list，就画单个热力图\n",
    "                self.draw_attention_map(\n",
    "                    attn_score,\n",
    "                    cross_attn_score,\n",
    "                    src,\n",
    "                    trg,\n",
    "                )\n",
    "            else:# 如果指定了heads_list，就画多个热力图\n",
    "                self.draw_attention_maps(\n",
    "                    attn_score,\n",
    "                    cross_attn_score,\n",
    "                    src,\n",
    "                    trg,\n",
    "                    heads_list=heads_list,\n",
    "                    )\n",
    "        return [self.mose_detokenizer.tokenize(self.pattern.sub(\"\", s).split()) for s in self.trg_tokenizer.decode(preds)] #将解码后的目标语言句子列表返回，并使用 mose_detokenizer 进行去标记化，最终得到翻译后的结果。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "834bf729a4c23a35",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-03-13T12:35:11.211029Z",
     "iopub.status.busy": "2025-03-13T12:35:11.210680Z",
     "iopub.status.idle": "2025-03-13T12:35:12.779514Z",
     "shell.execute_reply": "2025-03-13T12:35:12.778847Z",
     "shell.execute_reply.started": "2025-03-13T12:35:11.211005Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Loading vocabulary from ./wmt16/vocab ...\n",
      "Read 1524518 words (18107 unique) from vocabulary file.\n",
      "Loading codes from ./wmt16/bpe.20000 ...\n",
      "Read 20001 codes from the codes file.\n",
      "  8%|▊         | 10/128 [00:00<00:00, 196.30it/s]\n",
      "/usr/local/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: There are no gridspecs with layoutgrids. Possibly did not call parent GridSpec with the \"figure\" keyword\n",
      "  fig.canvas.print_figure(bytes_io, **kw)\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0wAAAHGCAYAAABHKQsgAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAWE1JREFUeJzt3Xd8FHXi//H3JiELIZVQQgkQOqGXkyaC/UBQ4Q4QEUSRs6EHiCcgIEiJpyCC3llABT0UFOudCChNOiJFMdRQEj2QE4QQAiHJfn5/5Mv+CMkgYHZmMK/n47EPyO5kP+9NJjP73mkeY4wRAAAAAKCAIKcDAAAAAIBbUZgAAAAAwAKFCQAAAAAsUJgAAAAAwAKFCQAAAAAsUJgAAAAAwAKFCQAAAAAsUJgAAAAAwAKFCQAAAAAsUJgAAAAAwAKFCQAAAAAsUJgAAAAAwEKI0wEAAACc5vP5tGfPHh0+fFg+ny/fY9dcc03Ax1+yZImWLFlS6PhvvPFGwMcHYI3CBAAAirV169bpzjvv1IEDB2SMyfeYx+NRbm5uQMcfN26cnn76abVs2VIVK1aUx+MJ6HgALo3HnL9kAAAAKEaaNm2qOnXqaNy4cYUWlqioqICOX7FiRT377LPq27dvQMcBcHkoTAAAoFgrXbq0tm7dqlq1ajkyfmxsrDZs2KCaNWs6Mj6AC+OkDwAAoFhr1aqV9uzZ49j49913n9555x3HxgdwYRzDBAAAirVHHnlEjz32mA4dOqRGjRqpRIkS+R5v3LhxQMc/ffq0XnvtNX355Zdq3LhxgfGff/75gI4P4MLYJQ8AABRrQUEFd7jxeDwyxthy0odrr73W8jGPx6OlS5cGdHwAF0ZhAgAAtjty5IjGjBmjZcuWFXoq7aNHj9qW5cCBAxd8vFq1ajYlgVu4af6E89glDwAA2K5v377as2ePBgwYoAoVKjh6Km23FKI9e/YoJSVF11xzjUqVKuXfwgX7uWn+hPPYwgQAAGwXERGhVatWqUmTJk5HkSS9/fbbeuWVV7Rv3z6tXbtW1apV0wsvvKCEhATddtttAR37yJEj6tmzp5YtWyaPx6Pdu3erRo0auvfeexUTE6MpU6YEdHwU5Lb5E87iLHkAAMB29erV06lTp5yOIUl6+eWXNXToUHXu3FnHjh3zH7MUHR2tF154IeDjDxkyRCVKlFBqaqrCwsL89/fq1UsLFy4M+PgoyE3zJ5zHFiYAwO9W8+bNL2l6j8ejTz/9VJUrVw5Qojy7d++2PDZizJgxAR3bLb7++msNHz5cY8aMUcOGDQucGS4yMtK2LImJiZo0aZJuv/12RUREaOvWrapRo4a2bdumjh076ueffw7o+HFxcVq0aJGaNGmSb/y9e/eqcePGysjICOj4KMhN82dx9+23317y9yQmJiokpOiOPOIYpkK4dQULFIZ93gFrW7Zs0WOPPabw8PBfndYYo2eeeUZZWVkBzTRjxgw9+OCDKlu2rOLi4vL9vXo8nmJTmKKjo5Wenq7rrrsu3/12nZnuXPv27VOzZs0K3O/1enXy5MmAj3/y5Ml8W5bOOnr0qLxeb8DHR0Fumj+Lu6ZNm/rPWnkxgoKCtGvXLtWoUaPIMlCYCuHGFSxwviNHjqhXr15aunRpvn3eBwwYwD7vwDkef/xxlS9f/qKmtePvZsKECZo4caKeeOKJgI/lZn369FGJEiX0zjvvOH5QfUJCgrZs2VLg5A8LFy5U/fr1Az5++/bt9dZbb2n8+PGS8oqzz+fTs88+e8FTjiNw3DR/Qlq/fr3KlSv3q9MZY9SwYcMiH5/CZMFtK1g4r3v37hc97YcffhjAJHmGDBmikJAQpaam5luh9+rVS0OHDmW+BJS35eBiVrJnJScnq1KlSgFMJP3yyy/q0aNHQMe4Emzbtk2bN29W3bp1nY6ioUOH6uGHH9bp06dljNGGDRv07rvvKikpSTNnzgz4+M8++6yuv/56bdy4UWfOnNHf/vY3ff/99zp69KhWr14d8PFRkJvmz+KuQ4cOqlWrlqKjoy9q+rN73BQlClMh3LiChfOioqKcjpDP4sWLtWjRIlWpUiXf/bVr1/7Va4oAxcWlni46Pj4+QEn+vx49emjx4sV64IEHAj6Wm7Vs2VJpaWmueEN63333qVSpUho1apQyMzN15513qlKlSpo2bZruuOOOgI/fsGFD7dq1Sy+99JIiIiKUkZGh7t276+GHH1bFihUDPj4KctP8WdwtW7bskqZfsGBBkWfgpA/AFSoiIkKbNm1S7dq18x0kvHHjRt188806cuSI0xEBV/j555918uTJfOXp+++/1+TJk3Xy5EndfvvtuvPOO23Lk5SUpOeff1633HKLGjVqVOBg8kcffdS2LE56//33NXbsWD3++OOF/hwaN27sSK7MzExlZGRc9F4m+H1y6/yJ/HJycnT69OmLOozmt6AwWXDbChY4X+fOndWiRQuNHz9eERER+vbbb1WtWjXdcccd8vl8mj9/vtMRAVfo3bu3KlWq5N9N9fDhw6pXr54qVaqkmjVr6vPPP9frr7+uvn372pInISHB8jGPx6O9e/faksNpQUEFr2xy9sDu4nxQfW5uroYOHaolS5aoWbNmev755y9prxcUDeZPd/n3v/+tI0eOqH///v77Jk6cqPHjxysnJ0fXXXed5s2bp5iYmICMT2Gy4LYVLJzXrFmziz7oc9OmTQFOk7d/9fXXX6/mzZtr6dKluvXWW/Pt816zZs2AZwCuBAkJCZo1a5Y6dOggSZo8ebJeeeUV7dixQyEhIZo8ebLmz5+vdevWOZy0ePm1XYcvdXfK3+Knn37SsGHDtGTJEh0+fLjA2bgC8eb42LFjeuyxx7Ro0SLNmjVLN9xwgyRp0KBB+uijjzRw4EAtXLhQ1atX19y5c4t8fFyYm+ZPSNdee63+/Oc/6+GHH5YkrVmzRu3bt9fTTz+t+vXr68knn1SnTp30/PPPB2R8CpMFVrA437hx4y562qeeeiqASf6/48eP66WXXtLWrVuVkZGh5s2b277Pe2pqquLj4wuUSWOM0tLSVLVqVduyAIUpVaqUduzY4X+D07lzZzVs2FDPPvusJGnXrl1q06YNu7EWY506dVJqaqoGDRqkihUrFlie3XbbbUU+Zp8+fXTkyBG1b99eycnJmjNnjj788EPdcccdWrVqla666ip99913uu666/S///2vyMe3EhwcrIMHDxbYJfHIkSMqX748W1bgiPLly2vRokX+0/8PHTpUycnJ/gs7L1iwQH/961+1e/fugIzPSR8sHDp0SNWrV/d/vXTpUnXv3t1/Eaxbb71VSUlJDqWDE+wqQRfrbFF58sknC33MrqKSkJBQ6Mr16NGjSkhIYOUKx0VGRurYsWP+wrRhwwYNGDDA/7jH47H10hC5ubmaNWuWf2vG+ReuXbp0qW1ZnPb222/rlVde0b59+7R27VpVq1ZNL7zwghISEgJSUqysWrVKK1euVNOmTW0bc+HChVqzZo0SEhLUunVrxcTEKD09XaNHj9ZVV10lSQoLC9OpU6dsyyTJ8lo3WVlZCg0NtTWL09wyf0I6ceKEYmNj/V+vWrUq39lGGzRooP/+978BG5/CZIEVLNzOqqgcOXLE1qJidaHcjIwMlSxZ0pYMwIW0bt1a06dP14wZM/Thhx/qxIkT+S5GuWvXLlvOjnfWX//6V82aNUu33HKLGjZsWGyv7/Lyyy9rzJgxGjx4sCZOnOhfZkVHR+uFF16w9Q1pfHz8RV8Us6iEhobqxIkTCg0N1Zo1a7R48WKVKVNGV199tX+aLVu2qE2bNrbkmT59uqS89zczZ87MdxB9bm6uvvrqK9WrV8+WLG7gpvkTUuXKlbV9+3ZVrVpVGRkZ2rp1q6ZOnep//MiRI4Ve/LmoUJgssILFheTm5mrq1Kl67733lJqaqjNnzuR7/OjRowHP4HRRGTp0qKS8levo0aPzLahyc3O1fv16Wz+tBayMHz9e119/vf71r38pJydHI0eOzHdg8Ny5c/27X9th7ty5eu+999S5c2fbxnSjF198UTNmzNDtt9+uZ555xn9/y5YtNWzYMFuzvPDCCxo+fLheffXVfHuXBNLNN9+s/v37a9iwYSpTpoykvHXHp59+6p+mRIkSeuSRR2zJc/bNpzFGr7zyioKDg/2PhYaGqnr16nrllVdsyeIGbpo/kXc5hsGDB2vkyJFasGCB4uLi1Lp1a//jGzduDOgp4ClMFljB4kLGjRunmTNn6rHHHtOoUaP05JNPav/+/fr44481ZsyYgI7tlqKyefNmSXkr1++++y7frhqhoaFq0qQJKxUHsSvJ/9e4cWNt375dq1evVlxcnFq1apXv8TvuuEOJiYm25QkNDVWtWrVsG8+t9u3b5z8e4Vxer1cnT560NUuvXr2UmZmpmjVrKiwsrMAppAPxIdjUqVM1aNAgDRs27ILPb9cZ2fbt2ycp7+D6Dz/8MGBnG7tSuGn+hDRmzBj9+OOPevTRRxUXF6d//etf+Ur9u+++q65duwZsfAqTBVawuJA5c+ZoxowZuuWWWzR27Fj17t1bNWvWVOPGjbVu3bqAXkfFLUXl7IXk7rnnHk2bNk2RkZEBHxMXh11JCipbtqzl677llltszfLYY49p2rRpeumll4r13gIJCQnasmVLgbONLVy4UPXr17c1ywsvvGDreJIUExOjOXPm2D7urzn3IqFnd1MsjvOpm+ZP5J2856233rJ8/FIvbnvJDK4IkydPNg899JDx+XxOR4ExJiwszBw4cMAYY0xcXJz55ptvjDHGpKSkmMjISFsy9O/f3xw/ftyWsXBlqV+/vvnoo4+MMcaEh4eblJQUY4wx3333nYmNjXUwmXOys7PNs88+a5o1a2ZKly5tSpcubZo1a2aee+45c+bMGVuz3H777SYqKsokJCSYLl26mG7duuW7FRczZswwlStXNnPnzjWlS5c27777rpkwYYL//3DO7NmzTcOGDY3X6zVer9c0atTIvPXWW07HspWb5s/s7GzzxRdfmFdeecWkp6cbY4z58ccfzYkTJ2zN4RZbt24177//vnn//ffN1q1bbRmTLUwXkJOTo6lTp+rdd9/Vrl27JEl16tTRnXfeqb/+9a8FNtkH0qpVq7Rs2TJ9/vnnatCgQYGxP/zwQ9uyQKpSpYoOHjyoqlWrqmbNmlq8eLGaN2+ur7/+Wl6v15YMb775pi3jXIyNGzdaHs/FvGk/diXJ79SpU7rxxhu1du1a3XDDDbrmmmskSdu3b9cTTzyhTz/9VIsXL7btJCXR0dHq1q2bLWO52X333adSpUpp1KhRyszM1J133qlKlSpp2rRpuuOOOwI+fnp6un/LeHp6+gWnDcQW9OnTp+svf/mLSpYs6T/hgpVA7rVwvueff16jR4/WoEGD1K5dO0l570EeeOAB/fzzzxoyZEhAxh06dKjGjx+v0qVL66uvvlLbtm39ZyZ2gtPz51kHDhzQH//4R6WmpiorK0s33nijIiIi9Pe//11ZWVnF6riysydgS05Ozrf1s0GDBnr99df1hz/8IWBjcx0mC+evYM9uft2+fbu+/PJLtWvXztYV7D333HPBx9305rk4GD58uCIjIzVy5EjNmzdPd911l6pXr67U1FQNGTIk3wGiRal79+6aNWuWIiMj1b179wtOa1dRmTt3rvr166ebb75Zixcv1k033aRdu3bpp59+Urdu3Zg3HZCYmKikpCTddtttioiI0NatW1WjRg29+OKLevPNN225sLKbPPXUU5o1a5b+/e9/q3Hjxvke27p1q2699Vbdc889Gjt2rDMBoczMTGVkZBQ462cgnXu9oaCgoEJ3OzP/d3KdQBxDlJCQoI0bNyo2NlYJCQmW03k8Hu3du7fIx79QrnHjxqlfv3757p89e7bGjh3rP9apqJUoUUI//PCDKlSoYHktKKc4MX+edfvttysiIkKvv/66YmNj/cvz5cuXa+DAgQG77pDbJCcnq1WrVqpfv76GDBnif1+enJysqVOnaufOnVq3bl3ADpdhC5OFZ555Rmlpadq8ebPlCvaZZ56xbQXLm053ObcQ9erVS1WrVtXatWtVu3btgB50GBUV5V+pR0VFBWycSzFp0iRNnTpVDz/8sCIiIjRt2jQlJCTo/vvvt/UCuvj/hg4dqocfflinT5+WMUYbNmzQu+++q6SkJM2cOdPpeLabO3eunn/++QLLcklq0qSJJk+erCeffJLC5KCwsLCAnhK4MEuXLvWfnS7gxz8U4tziEagScjkOHjyotm3bFri/bdu2OnjwYMDGrV69uqZPn66bbrpJxhitXbvW8sQTZ7cS28WJ+fOslStXas2aNQWugVW9enX9+OOPjmRywtixY3XjjTfqgw8+yPfhRtOmTdW7d291795dY8eO1XvvvReYALbs+HcFqlOnjpk/f77l4++9956pXbu2jYkAdwoLCzP79u0zxhhTpkwZ8+233xpjjElOTjZxcXEOJive/vWvf5latWoZj8djPB6PqVy5spk5c6bTsRzh9XpNamqq5eOpqanG6/XamMiY999/3/To0cO0atXKNGvWLN+tuDh06JC56667TMWKFU1wcLAJCgrKdyuOsrKyzI4dO0x2drZjGRo0aGAmTpxY4P7x48ebhg0bBmzcjz76yFSoUMF4PB4TFBTkX3adf7Nr3nDL/BkdHW2+//57Y0z+Y1JXrlxpypcvb1sOp5UtW9Z8/fXXlo9v2LDBlC1bNmDjs4XJwoEDB/xX2i5M69atlZqaamMiaf78+ZbHiRS3XWzc4L///a9WrVpV6IWE7dzf3GkxMTE6ceKEpLwLy23btk2NGjXSsWPHlJmZ6XC64ik9PV19+vRRnz59CuxKsmfPnmJ3xs3IyEgdPnzY8tp5hw4dUkREhG15pk+frieffFL9+/fXJ598onvuuUcpKSn6+uuv9fDDD9uWw2n9+/dXamqqRo8erYoVKzp+JraVK1fq1Vdf1d69e/X++++rcuXKevvtt5WQkJDvYrKBkJmZqUceeUSzZ8+WlHetxxo1auiRRx5R5cqVNXz48ICOf65x48apV69e+uqrr/zHMK1evVpLliwJ3Kf3ytv17Pbbb1dGRoYiIyO1c+dOR3fJc8v8edNNN+mFF17Qa6+9JilvF82MjAw99dRTxepSMydOnFCFChUsH4+Li/O/FwmIgFWxK1y5cuXMxo0bLR8PdJM937Rp00x4eLgZNGiQCQ0NNffff7+54YYbTFRUlBk5cqRtOZDnzTffNKGhoSY8PNxUq1bNVK9e3X9LSEiwJYNbPv3q3bu3mTJlijHGmKefftqUK1fO3HfffaZatWrF6oxfbnL11Veb06dPF7h/x44dpnLlyg4kclbPnj1N9+7dLR/v3r276dGjh2156tata9555x1jTP5PjEePHm0efvhh23I4LTw83GzevNnpGMYYY+bPn29KlSpl7rvvPuP1ev2/kxdffNF06tQp4OM/+uijpkWLFmblypWmdOnS/vE//vhj07Rp04CPf76NGzeaPn36mObNm5vmzZubPn36mE2bNtk2/vLlyx3dymaMe+bPtLQ0k5iYaOrXr29CQkJM69atTWxsrKlbt6756aefnI5nm1/b8+v99983derUCdj4nPTBQq9evZSTk6MPPvig0Mf/9Kc/KTg4OKCftpyrXr16euqpp9S7d+98B3GPGTNGR48e1UsvvWRLDuSJj4/XAw88oBEjRigoKMiRDJ06dVJqaqoGDRpU6Kdfdl1r5+jRozp9+rQqVaokn8+nZ599VmvWrFHt2rU1atSoYn/xQyd06tRJHo9Hn376qf8sU9u3b9d1112nnj17atq0aQ4ntNfZg4UbNGigoUOHql69ejLGaPv27Zo6daqSk5O1bt06NWjQwJY8YWFh2r59u6pVq6by5cvriy++UJMmTbR79261bt1aR44csSWH0xITEzVnzpxCz+hot2bNmmnIkCHq169fvnXs5s2b1alTJx06dCig41erVk3z5s1T69at842/Z88eNW/e/FfP4vd782t78FStWjXgGdw0f+bk5Gju3Ln69ttvlZGRoebNm6tPnz4qVaqU09Fsc/bkPZ999pkaNmyY77HvvvtOXbt2Vb9+/fT0008HJkDAqtgV7vvvvzfh4eGmVatWZt68eWbr1q1my5Yt5t133zVXXXWVCQ8PN9u2bbMtT6lSpcz+/fuNMXlbv7Zs2WKMMWbXrl2mTJkytuVAnjJlypg9e/Y4msEtn365SVZWlklLSzMHDhzIdytuMjMzTdu2bU3Pnj2Nz+cz3333nSlfvrwZMmSI09Ecs3btWpOYmOg/BuLsMRL169c3a9assTVLQkKC/9P6Fi1amFdeecUYY8yiRYtMTEyMrVmctGjRInPTTTf5j4F0UqlSpfw5zt3ql5KSYsvxbaVKlfKPee74W7Zsse3afufKyckx8+fPN+PHjzfjx483H374ocnJybFt/HP/Tgu72cFN8yeMOXXqlGnbtq0JDg42f/zjH82QIUPM4MGDzc0332yCg4NNmzZtzKlTpwI2PscwWUhMTNQXX3yhAQMG6I477vB/em+MUb169bR48WLbPo2U8vbNPHr0qKpVq6aqVatq3bp1atKkifbt2+c/Fz3sM2DAAL3//vu27ld+vvj4eNf87nNzc/Xxxx9r+/btkqQGDRro1ltvVXBwsC3j7969W/fee6/WrFmT734TwFMCu1mpUqX02WefqWPHjurZs6e++uor9evXT88995zT0RzTunVrff/999qyZUu+6+o1bdrU9izXXXedPv30UzVr1kz33HOPhgwZovnz52vjxo2/ermA35NevXopMzNTNWvWVFhYWIHrCx49etS2LHFxcdqzZ4+qV6+e7/5Vq1apRo0aAR+/ZcuW+uyzz/TII49Ikv89x8yZM9WmTZuAj3+uPXv26JZbbtEPP/ygunXrSpKSkpIUHx+vzz77TDVr1gx4hs2bN+f7Ojs7W5s3b9bzzz+viRMnBnx8yV3z59tvv+0/vm7t2rWqVq2apk6dqho1ati2N4nTSpYsqWXLlvmvj7pixQpJecvxCRMmaMiQIQG9Dia75F0EN6xg77vvPsXHx+upp57SP/7xDz3++ONq166dfwX7+uuv256pOMvNzVWXLl106tQpNWrUqMCC9Pnnnw94hsWLF2vKlCl69dVXC6zk7VTYynXnzp22rlzbtWunkJAQDR8+vNDdE5s0aRLwDE4rbJedgwcP6sYbb1SXLl3ynQo/EBfhvBKdOXNGZ86cUXh4uK3j+nw++Xw+/+6S8+bN0+rVq1W7dm098MADtl4U3UlnT3Bg5e6777YpSV4h+Ne//qU33nhDN954oxYsWKADBw5oyJAhGj16tL/IBMqqVavUqVMn3XXXXZo1a5buv/9+JScna82aNVqxYoVatGgR0PHP1blzZxljNGfOHP9p148cOaK77rpLQUFB+uyzz2zLcr7PPvtMzz33nJYvXx7wsdwyf7788ssaM2aMBg8erAkTJuj7779XjRo1NGvWLM2ePduRU+IXRxSmS8QKFpI0YcIEjRkzRnXr1lWFChXyvUH3eDxaunRp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j23LdLfMn6VKlTIHDhwwxhjTo0cPM3bsWGOMMampqcXmAzA3LMcpTIVwwy/mfKxg87hhIWqMOxdgTq1g3bByLV++vFm0aFGB+xcuXGjKly9vSwZj3DN/vv322+bNN980xhizceNGU7ZsWePxeIzX6zVz5861LYcbBAUFmcOHD1/09Hbsejx48GAzceLEgI5xJZg0aZJJTEw069atMxEREWblypXmX//6lylXrpyZPn26I5n+8Y9/GK/Xa6pUqWJ2795t27g+n8988803ZsqUKaZr164mJibGBAcH+3e3ttOgQYPMkCFDCtz/2GOPmYceesiWDFdffbX56KOPjDHG9O7d2/zxj380q1atMv369TMNGjSwJYNb5s9GjRqZadOmmdTUVBMZGWnWrFljjMlbttu966pT3LAc56QPhWjWrJkOHTp00QfOt2nTJt/FswLh7rvv1rx58zRy5MiAjfFr9u3b59jYZzVs2FBbt25VQkKCWrVqpWeffVahoaF67bXXAvrzP1+tWrX08ccfq1u3blq0aJGGDBkiSTp8+LBt1/wxxmjz5s1avny5li9frlWrVik9PV2NGze29axwffv21csvv6znn38+3/2vvfaa+vTpY0uGXr16acCAAZo8ebL/YourV6/W448/bnkgdyC4Zf686667/P9v0aKFDhw4oB07dqhq1aoqW7asbTncwBij0aNHKyws7KKmt+PMp7m5uXr22We1aNEiNW7cuMBJH87/WyoqQ4cO1fjx41W6dGkNHTrUcjqPx2PLyUGGDx8un8+n66+/XpmZmbrmmmvk9Xo1bNgwPfLIIwEf3+pnUK5cOTVv3lz//Oc//fcF6ndyVpkyZZSRkaEmTZqoQ4cOGjhwoNq3b6/o6OiAjnvWuT8Lj8ejmTNnavHixWrdurWkvEtFpKamql+/frbkGTVqlE6ePClJevrpp9WlSxe1b99esbGxmjdvni0ZnJ4/zxozZozuvPNODRkyRNdff73atGkjSVq8eLGaNWtmWw4rN9xwg/bu3au9e/cGbAw3LMc5rXghgoKC9Je//OWifzH//Oc/lZycHNA3RI8++qjeeustNWnSpFivYBctWqSTJ0+qe/fu2rNnj7p06aJdu3b5F6LXXXddwDNI0vz583XnnXcqNzdX119/vRYvXiwp7/pMX331leXpnItSTExMvhVsx44dbVvB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",
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['man in a small white boat on a lake.']\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 12%|█▏        | 15/128 [00:00<00:00, 149.67it/s]\n",
      "/usr/local/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: There are no gridspecs with layoutgrids. Possibly did not call parent GridSpec with the \"figure\" keyword\n",
      "  fig.canvas.print_figure(bytes_io, **kw)\n"
     ]
    },
    {
     "data": {
      "image/png": "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mZ3the21117zKK+ki9mVpLxc2K59+/YaN26c/va3v7ktf++99/SPf/xDq1atKlP+zTffrB49eui+++5zW/78889r0aJF+uCDD8qUD3jL8ePHjbyene0TTk9fg/yFMSEwvPnmm3r88ceVnp4uSYqPj1dKSorbDIrnqmrVqvrPf/6ja6+9tsxZp1q6dKnr671792r8+PEaPHiw24drc+bMUWpqqm6//XavrtvbnE6npkyZohkzZrguX1C7dm2NGDFCY8aMcTuUKlCZfA6Vd5GRkdqyZYsSExMVFxenJUuWqGXLltq6dasuv/zygL9kRdFsqmlpaSpqdSzLUvPmzfXKK69476gIr5xpVcElJyfbdevWtTdu3Fjsvg0bNth169a1H3vsMd8XBq+KjIx0nWx6qt27d9tRUVFeyd+5c2ex5Tt37rQjIyPLnG9CVlZWqW+w7ZSUlBInXDl69GjAT6hQWFhoT5w40Y6Pj7eDgoJcfwuPPvqo/fLLL3tlHS1btrSff/5527b//8ndTqfTvvPOO+3k5GSvrMMXGBNKx1d/D7m5ufavv/7qtTzbtu3ExER769atXs38s8svv9yeO3duseVvvvmm3a1bN6Pr9jYT44AvX09NPIeGDBliZ2dnF1uek5NjDxkyxKvrMqFOnTr2pk2bbNs++dpd9FxdsWKFHR0d7c/SzmrLli12VFSUfckll9hz5861169fb69fv95+88037Xbt2tmVK1e2t2zZ4pV10UiVQuPGje133nnntPe//fbbdqNGjXxYUeCZM2eOffz48WLL8/Ly7Dlz5vihIs9VrVrVXrFiRbHly5cvt2NjY8ucX7duXXvKlCnFlk+ZMsWuW7dumfNNsCzLNbva6W5Fj4FtOxyOEgfjAwcOBPw2SklJsRs0aGD/5z//sStVquRqpObPn2937NjRK+uIiIiw9+zZY9v2yb+3okE6LS3NrlWrllfW4QuMCaVTnv8eZs+ebffr188+evSosXVUqlSpxJkAt2/fbleqVMnYesuL8vz8se3T1//bb7/ZQUFBZc4/cOCAfc8999hNmza14+Li7CpVqrjdyqp///721KlTbdu27YkTJ9rVq1e377jjDrtevXp2nz59ypxvUt++fe0+ffrYTqez2H1Op9O+8cYb7b59+3plXZwjVQo//PCD6/jfknTs2FEZGRk+rOjcvfPOO6c9P2HdunXnnDtkyBBdffXVqlGjhtvyI0eOaMiQIeXiOlJXXXWVkpKS9OGHH7qulXH48GE9/PDDuvLKK8ucn5KSojvuuENLlixxnYe1atUqLViwQLNmzSpzvgnl+ToS/mDbdonnP2zcuFFVq1b1Q0Wl9/rrr2vmzJm64oorNHz4cNfy1q1ba9u2bV5ZR5UqVXTkyBFJJ6/z8f3336tly5Y6fPiwjh496pV1+IIvxoRff/1VY8eOdV0s1/7TUfjeOlza1Jggmf17ML19/u///k/z5s1TjRo1lJiYWOz8sbJuG+nkBapnzZqlp59+2m35yy+/XObrkPH8OTtT2yg7O1v2yR0VOnLkiNshvoWFhfrss8+KvVc6FwMHDtSuXbs0bNgwr57HV+T555/X8ePHJUmPPPKIQkJCtGLFCt18880Bfy21onM/S9omlmXp4Ycf9tphuzRSpRAdHa39+/ef9oXtl19+UeXKlX1cleeee+45PfLIIxo8eLA+/PBDDRkyROnp6fruu+907733lin7dC94P/74o9sF/ALZlClTdNlll6levXquKVE3bNigmjVr6o033ihz/uDBg9W0aVM999xzrpO4mzZtqmXLlhWb4CJQdOvWTdLJE+snT56soUOH6oILLvBzVYGnaHZGy7LUuHFjt7+FwsJC5eTkuDUngeinn34qcSpsp9Op/Px8r6zjsssu05dffqmWLVuqb9++GjFihL766it9+eWXuuKKK7yyDl/wxZgwePBgZWRkaMKECapdu7aRWfVMjQm++HswvX1uv/12rV27VrfddpuRN6mSNG3aNN188836/PPPXWPA6tWrtXPnTr377rtlyja1fUaPHq0nnnhCkZGR5fr5I5nbRkUTihTV/2eWZSklJaXM6/nmm2+0bNkytW7dusxZf1ZQUKBPPvlEvXr1knTynPjx48d7fT2mHDlyRDVr1jzt/bVq1XJ9qFdWTDZRCrfccosKCgpO+8J28803KygoSG+//baPK/NMkyZN9Nhjj6l///6qXLmyNm7cqAYNGig5OVmHDh3S888/73Fm27ZtZVmWNm7cqObNmys4+P/35oWFhdqzZ4+uvvrqgN82RXJzc/Xmm29q48aNqlSpklq1aqX+/fuXixm4TKtcubI2b96sxMREf5cScObMmSPbtjV06FBNnz7d7cOD0NBQJSYmuk4mD1QXX3yxRo0apdtuu83t9WHixIn68ssv9c0335R5HYcOHdLx48cVHx8vp9Opp59+WitWrFCjRo306KOPqkqVKl74TczzxZhQuXJlffPNN2rTps05Z5yNiTFB8s3fg+ntExkZqS+++EJdunQxkl/kxx9/1L///W/XXt+mTZtq+PDhZd4jZWr79OjRQ++//75iY2PL9fNHMreNli5dKtu2dfnll+vdd99123sWGhqqevXqKT4+vszrueSSS/TPf/5THTt2LHNWSSIiIrR169Zi08OXBxdddJEmT56sm2++ucT733nnHT3yyCPavn17mdfFHqlSeOyxx9ShQwd17NhRo0ePVpMmTWTbtrZu3app06YpLS1NK1eu9HeZZ5WRkaHOnTtLOjnHflE3PnDgQHXs2PGcXvSKLmi7YcMG9erVS1FRUa77il7wTvdEDkSRkZG66667jOU7nU7t2rWrxOuSXHbZZcbW6w2XX365li5dSiNVgqLZterXr6/OnTsbbbxPnDhR4vOnrBcNTU5O1u23366ffvpJTqdT7733nrZv367XX39dn3zySZmyi5z6hqK8fcJ5Kl+MCQkJCcUONfI2E2OC5Ju/B9PbJyEhwSfXcbrgggs0efJkr+ea2j6nHu5dnp8/krltVHQkx549e1S3bl1j12j797//rfHjxys5OVktWrQotp3K+vxt3759idfZKg/69eun0aNH66KLLlKLFi3c7tu8ebPGjh3rtVNOaKRKoVmzZvryyy81bNgw9evXz/VHYdu2mjRpooULF6p58+Z+rvLsatWqpUOHDqlevXqqW7euVq5cqdatW2vPnj3n/GJSdEHbxMRE3XLLLQE/3e+ZnOnibZLK/Ee3cuVK3Xrrrfrhhx+Kbe/yMEX8Nddco/Hjx2vz5s26+OKLFRkZ6XZ/ebhWmGlFA6h0cgrxP58zUJaBbefOnRo6dKhWrFjhtrzosNqyPn9uuOEGffzxx5o4caIiIyOVnJysv/zlL/r444+9co5gkfT0dL322mtKT0/XjBkzVKNGDX3++eeqW7duuXgdlXwzJkyfPl3jx4/XSy+9ZOzDCxNjQnZ2tut53rZtWx07dkzHjh0r8bFl+XswvX2mTp2qcePG6cUXXzT64dHhw4e1evXqEj8cKcuYY2r7NGjQQN99953i4uJUs2bNcvv8kcw/h3744Qf98MMPp72/rB+exsbGKjs7W5dffrnbcm+NCffcc49Gjx6tzMzMEsd8b1+PyZuSkpK0aNEitWnTRldeeaWaNm3q+rBr0aJFat++vR5++GGvrItD+zy0YcMGtwt7mTzswtvuuOMOJSQk6LHHHtO//vUvPfjgg7r00ku1Zs0a3XTTTXrllVf8XaJf/fmwovz8fB09elShoaGKiIjQoUOHypTfpk0bNW7cWCkpKSUejx3o55Kd6bph5aER9IWjR49q3Lhxevvtt3Xw4MFi95dlG1166aUKDg7W+PHjS3z+mDhO3tuWLl2qa665Rpdeeqn+97//aevWrWrQoIGeeuoprVmzRu+8846/S/SYqTGhSpUqOnr0qAoKChQREVHs0+ayvh5JZsaEoKAg7du3TzVq1JDD4Sjx03hvvNEzvX18sf0//vhjDRgwQDk5OYqOjnbbVpZllWkdpuqfMWOG/v73vys8PFxDhw5V/fr1NWHChHL3/JHM/x+XNGb++Xyvsmjfvr2Cg4M1YsSIEs/jO/WDvXNxuvq9tf1NO3HiRIkXTe/Xr59GjRqlsLAwr6yHRqoMTpw4oRMnTrgdzhbInE6nnE6n6zymt956S8uXL1ejRo00fPhwj3efV61aVTt27FC1atVcJ4eejjcGHX/YuXOn7r77bj344IOuky7PVWRkpDZu3FjiCf2oGO699159/fXXeuKJJzRw4ED961//0k8//aSXXnpJTz31lAYMGHDO2ZGRkVq7dq2aNGnixYqLM3XooCR16tRJffv21ejRo93OqVi9erVuuukm/fjjj2Vehz95c0yYM2fOGe/3xsVavT0mSCeb5aKm/9SLz5akLG/0TG8fX2z/xo0b69prr9XkyZMVERFR5rxT+aL+EydOuJoQqXw9fyTz2ygrK8vt+/z8fK1fv14TJkzQpEmTyjzBTkREhNavX6+LLrqoTDmnc6a9aZLK5SF/JtBIldJrr72mdevWqWPHjhowYIAefvhhTZ06VQUFBbr88ss1f/58xcXF+bvMszp+/Lg2bdpU7I2SZVm6/vrrPcqaM2eO+vXrp7CwMJ+8aPvLmjVrdNttt5V5CujLL79c48aN09VXX+2lyhBo6tatq9dff13du3dXdHS01q1bp4YNG+qNN97QvHnz9Nlnn51z9iWXXKJp06YZO/nd9KGDkhQVFaXNmzerfv36bo3U3r171aRJE9dUu+UBY0LZ8iUOB46MjNTmzZvVoEEDf5dyznj+eG7p0qUaPXq01q5dW6acyy67TMnJyerZs6eXKnP3v//9T507d3abREw6OaPfihUrAvq87tWrV+viiy9WUFBQiffn5eXpww8/1P/93/+VeV2cI1UKkyZN0qRJk3TppZdq7ty5WrZsmT744ANNnDhRDodDzz33nB599FG98MIL/i71jBYsWKCBAweWeMjRubxROrU5Wrx4sbp3765u3brpwgsvLHOtgSQ4OFg///xzmXPuv/9+jRkzRr/88otatmxZ7NO6QDze+LnnntNdd92l8PBwPffcc2d87AMPPOCjqgLXoUOHXG+KoqOjXXtiu3TporvvvrtM2f/4xz80btw4TZ48ucTnT1nPFxg8eLCCg4P1ySefGJtuOzY2Vvv27VP9+vXdlq9fv1516tTx+vpMMTUmnHp+SHZ29hkf642JELw9JpSUP2jQIB04cMAr+aa3j6+3f69evbRmzRqvNVL+eP548//XF/m+3kYlqVmzpldmi7v//vs1YsQIPfjgg0beU/To0cN1mOWpsrKy1KNHj4A+tK9Tp05utUdHR2vDhg2uv7XDhw+rf//+Xmmk2CNVCo0aNdLEiRPVv39/rVmzRh06dNDbb7/tmo3u888/1/Dhw8+6G9TfGjVqpKuuukrJyclnnF//XNx5551aunSp0tPTFR8fr27durkaq0aNGnl1XaZ89NFHbt/btq19+/bp+eefV0JCgj7//PMy5ZfHc4zq16+vNWvWKC4urtib31NZlqXdu3eXeX07d+7U119/XeKnj8nJyWXON61Vq1b65z//qW7duqlnz55q06aNpkyZoueee05PP/10mQ5dO/X5c2qT4609Rr44dHDs2LFatWqV/vvf/6px48Zat26dfv31Vw0aNEiDBg1yTV4T6EyNCb48P6To9zA1JpjIN719fL39X3nlFU2cOFFDhgwp8Y2wp3tceP6cnS+30aZNm4rl7tu3T0899ZQKCgq0bNmyMuWbfk/hcDj066+/qnr16m7Ld+zYoXbt2p21EfUnh8OhX375xdVInXoEhHTyYsy1a9cu9j7jXNBIlUJYWJh27drluq5DWFiYNm3a5Dou9aefflL9+vWLzdAVaKKjo7V+/Xqje4x++ukn/e9//9PSpUu1dOlS7dixQ7Vr1y4X5z78+UXJsixVr15dl19+uaZOnaratWuXKZ/jjc9s1qxZuvvuu1WtWjXVqlWr2InX69at82N1pTNt2jQFBQXpgQce0KJFi3T99dfLtm3l5+fr2Wef1YgRI8452/T5AqYPHZROnlNx7733avbs2SosLFRwcLAKCgo0YMAAzZ49+7SHYQQaU2OCL88PkcyPCd7ON719fL39vf1GmOfP2flyGxU1an9+m92xY0e9+uqrZf7QytR7iptuukmS9OGHH+rqq692m5ShsLDQ9Vq3YMGCc8r3hdI0UvHx8V75QIFD+0ohPz/f7YkUGhrq9slRcHCwV/cmpKWlKSMjo9ggXNbjgf/2t79pyZIlRhupKlWqKC4uTlWqVFFsbKyCg4OLfZpRVqa2z6mfTBR9faaBzlNFL2ol1W9ZltcaKVPbZ/To0SUutyxL4eHhatiwoW644Qa3awV54sknn9SkSZP00EMPlaXMszK1fSRp1KhRrq979uypbdu2ae3atWrYsGGZD7Po1q2bDh8+rFdeeUVbt26VdHIa7mHDhp3zjI+nfqJo+tBB6eRr56xZs5ScnKzNmzcrNzdXbdu2LXcTsJgaE05949atWzd98803eumll5Senq533nlHderU0RtvvHHGvcOeMD0meDvf9Pbx9fb3xqfhp+L5c3a+3EZ79uxx+97hcKh69epeu0yMqfcUReOJbduqXLmyKlWq5LovNDRUHTt21J133lmGyisWGqlSSktL0y+//CLp5JNr27ZtysnJkaQSj989F7t371afPn20efNmt08xij6ZL2uz9vzzz6tv37765ptvSnyjVJZzXB5++GEtWbJE69evV9OmTdWtWzeNHz9el112WbFpxc+V6e0jnTzUYtq0adq5c6ekk4cWjBw5UnfccUeZs03Xbzp//fr1WrdunQoLC12fvO/YsUNBQUFq0qSJ/v3vf2vMmDFatmyZmjVr5nH+77//rr59+5apxjPxxfNHOnm+4OLFi0s8PPHVV18959w1a9bo6quvVnh4uNq3by/p5B6wyZMna+HChfrLX/7icWZsbGyxwwT/PJOUt6e6Nfk35kumx4R3331XAwcO1IABA7R+/Xrl5eVJOnl+wuTJk8s0cUkRk2OC6XzT28cX23/ixImnvc+yLE2YMOGcs3n+nJ3pbVSvXj1j44Fkbkx77bXXJEnVq1fX448/7pqVce/evfrggw/UtGlTVatWrUy1+4Iv3rcXheMsLMuyHQ6HbVlWsVvRcofDUeb19O7d277hhhvs3377zY6KirLT0tLsb775xm7fvr39v//9r8z5L7/8sh0cHGxHRUXZ9erVsxMTE123+vXrlynbsiy7Ro0admpqqr19+/Yy11oS09tnwoQJdmRkpD1+/Hj7ww8/tD/88EN7/PjxdlRUlD1hwgSv179lyxav1m96+0ybNs2+6aab7KysLNeyw4cP23/729/s6dOn27m5ufYNN9xgX3XVVeeUP3ToUPuFF14oc52nY3r72LZtP/7447bD4bDbt29v33DDDfaNN97odiuLLl262IMHD7bz8/Ndy/Lz8+3bb7/d7tq16zllLlmyxHWbPXu2vXjxYrdlS5Yssb/66it79uzZZaq9iOm/MV/xxZjQpk0be86cObZt23ZUVJSdnp5u27Ztr1u3zq5Zs2aZfwfbNjsmmM43vX18sf3btGnjdmvevLkdERFhR0dH223bti1zNs+fMzO9jUyOB7Zt/j1Fz549XWPy77//btesWdO+4IIL7PDwcPvf//53mfNN8tX7dtu2bRqpUti7d2+pbmUVFxdnb9y40bZt246Ojra3bdtm27ZtL1682G7Tpk2Z82vWrGlPmjTJLiwsLHPWn23YsMGeMWOG3adPH7tatWp2fHy83b9/f/ull17yWmNlevtUq1bNnjt3brHlc+fOtePi4sqcb7p+0/nx8fH2li1bii3//vvv7fj4eNu2bXvt2rXnvK0mT55sV6tWzb799tvtKVOm2DNmzHC7lZXp7WPbtl2rVi379ddf90rWn4WHh9tbt24ttnzLli12pUqVypzvcDjsX3/9tdjyAwcOeG3AMf035iu+GBMqVapk79mzx7Zt9zd56enpdlhYWFl/Bdu2zY4JpvNNbx9fbP+SZGVl2X369Cnz6wjPn7MzvY1Mjge27Zv3FN9//71t27Y9a9Ysu1WrVnZhYaH99ttv202aNClzvkm+et9u27bNoX1nsWnTJrVo0aLU58ps2bJFF110UbF590ujsLBQlStXliRVq1ZNP//8sy666CLVq1fPK1NlnjhxQrfccotXz/sp0rp1a7Vu3dq1q33jxo2aNm2a7r33XjmdTq8cFmR6++Tn56tdu3bFll988cUqKCgoc77p+k3nZ2Vlaf/+/cUO2/vtt99c59rExsae86QrM2fOVFRUlGui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9kgBAAAAgIdopAAAAADAQzRSAAAAAOAhGikAAAAA8BCNFAAAAAB4iEYKAAAAADxU5kaqe/fuGjlypBdKOTd79+6VZVnasGGD32oAAAAAcH5hjxQAAAAAeIhGCgAAAAA85JVGqqCgQPfdd59iYmJUrVo1TZgwQbZtS5Ly8vI0duxY1alTR5GRkerQoYOWLFni+tmDBw+qf//+qlOnjiIiItSyZUvNmzfPLd/pdOrpp59Ww4YNFRYWprp162rSpEluj9m9e7d69OihiIgItW7dWt9++603fjUAAAAAKMYrjdScOXMUHBys1atXa8aMGXr22Wf18ssvS5Luu+8+ffvtt5o/f742bdqkvn376uqrr9bOnTslScePH9fFF1+sTz/9VN9//73uuusuDRw4UKtXr3blJyUl6amnntKECROUlpamuXPnqmbNmm41PPLIIxo7dqw2bNigxo0bq3///iooKDhtzXl5ecrOzna7AQDOP067UAXKlyTGAwBAqVl20a6jc9S9e3ft379fW7ZskWVZkqTx48fro48+0oIFC9SgQQNlZGQoPj7e9TM9e/ZU+/btNXny5BIze/furSZNmmjKlCk6cuSIqlevrueff1533HFHscfu3btX9evX18svv6xhw4ZJktLS0tS8eXNt3bpVTZo0KXEdjz/+uFJSUootv6LpWAUHhXm8HUrDDjZ7JKVz41aj+frj/9dYfGio0Xw7//SNtTc4IiOM5ltBhp8/uceM5vuCIzbGaL6zXs2zP6gMfm9W2Wh+3Oe7jOYX/vab0XxT0u0t2qPir589Qvoq2Aoxsk67sNBIrovTcD78y/B4rLK9NQwMpreRYUGxsUbzP9vytdH8q+t3MJovg6+hBXa+vi54V1lZWYqOjj7jY73yzqxjx46uJkqSOnXqpJ07d2rz5s0qLCxU48aNFRUV5botXbpU6enpkqTCwkI98cQTatmypapWraqoqCh98cUXysjIkCRt3bpVeXl5uuKKK85YQ6tWrVxf165dW5K0f//+0z4+KSlJWVlZrltmZuY5//4AgPKrvpqoi66VJGVmZjIeAABKJdhkeE5OjoKCgrR27VoFBQW53RcVFSVJeuaZZzRjxgxNnz5dLVu2VGRkpEaOHKkTJ05IkipVqlSqdYWE/P9PDYuaOqfTedrHh4WFKSzMzJ4nAED54bCCFGyfHEPO9ukj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",
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['a man with a bucket and a girl in a hat on the beach.']\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  6%|▋         | 8/128 [00:00<00:00, 176.10it/s]\n",
      "/usr/local/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: There are no gridspecs with layoutgrids. Possibly did not call parent GridSpec with the \"figure\" keyword\n",
      "  fig.canvas.print_figure(bytes_io, **kw)\n"
     ]
    },
    {
     "data": {
      "image/png": "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pm666SZ98cUXqly5sm655RbT8XADOXr0qK0T+GNiYlSxYsVrmMi7nTlzRl26dDEdw+vMmjXriu87aNCga5gkb+np6Zo4caIef/xxffXVV8Zy5GfOnDl67733JGWdBmTx4sUaPny4Vq1aZTihdO7cOQUGBmZbfvr0afn7+xtI5D1at26t6tWrX/Eexkvnn10r7JG6Cj/88IMqV658xScGxsfHq2LFivLx8bnGybIbO3asFi5cqLFjx6p///7au3evwsPD9dFHH2nGjBnasmVLoWdCwYuIiNDEiRPVqVOnLN9y7d27V5GRkfrtt9+M5lu/fr3at2+vFi1a6Ouvv9b+/fsVHh6uyZMna8eOHVqyZInRfAD+vL59++q2227LMpob8hcWFpbl+q+//qrk5GTPB8WzZ88qMDBQN910k2feJlOKFy+uvXv3qmrVqkZz5KVo0aI6ePCgQkND9fTTT+vChQuaO3euDh48qKZNm+rMmTOmI6pDhw669dZbNW7cOJUoUUJ79uxRlSpV1K1bN2VmZrIt9CLskboKfzzZMj+X5vcxgSFLbwxHjx7N8YRff39/nTt3zkCirEaMGKHx48dr6NChKlGihGd5mzZtNHv2bIPJcKP67bffdO7cuSzr83379unVV1/VuXPn1KlTJz322GMGE3qP6tWr68UXX9Q333yjevXqqUiRIlluN7k3xcmOHj3q+ff777+v119/XW+++aZq1aolSTpw4ID69++v//u//zMV0aNt27Zav369o4uUN0wDMmXKFLVt21Y7duxQamqqnn32We3bt0+nT5/Wpk2bTMfzWunp6bpw4cIVnXJTUChSV8lbNsIMWXpjCAsL0+7du7OV/C+//FJ16tQxlOp/vvvuO73//vvZlt90003G95bhxjRw4EBVrFjRc+j1yZMn1apVK1WsWFHVqlVT7969lZGRoR49ehhO6nxvvPGGihcvrvXr12v9+vVZbnO5XBSpK/Diiy9qyZIlnhIlSbVq1dL06dP18MMPq3v37gbTSe3bt9eIESP03Xff6dZbb1WxYsWy3P7AAw8YSvY/3jANSN26dXXw4EHNnj1bJUqUUFJSkjp37qwBAwaoQoUKpuM53qeffqpTp06pd+/enmUTJkzQuHHjlJ6erjZt2uijjz5SyZIlr3kWitRV8paNMEOW3hiGDh2qAQMG6MKFC7IsS9u2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lbxlI3zJpk2bskzI265dO9ORsjl8+LBiY2N15513qmjRorIsixOXr1B4eLj+85//eCYXxfUpISFBGRkZKlWqVJblp0+flq+vr7Hz4bxRQECADh06lOs0FfHx8apRo4YuXLhQyMmyqlKlij766CM1a9ZMJUqUUHR0tMLDw3X48GE1btw4x0O3TViyZIkWL16suLg4paamZrlt586dhZ7nk08+0RNPPKGTJ0/K5XIpt488TjkvZf369Wrfvr1atGihr7/+Wvv371d4eLgmT56sHTt2aMmSJaYjOt4vv/yiYcOGeUrKH3/nTvg95zeM/H/+8x9DybxD2bJl9cUXX6hJkyY53r59+3Z16NBBv/766zXP4twDhb3EDz/8oNtvvz3X25s1a6a4uLhCTJTd5XsqWrRooRYtWhjNk5tTp06pa9euWrdunVwulw4dOqTw8HD17dtXJUuW1NSpU01HdLwXXnhBzz//vN55551sH7Jx/ejWrZs6duyop556KsvyxYsX67///S/zSNkQFBSkkydP5lqkTpw4kWWkU1N+/fXXHA9POnfunNEvmi4/B2nWrFl64YUX1Lt3by1fvlx9+vRRbGystm/frgEDBhjJ16lTJ3Xq1ElJSUkKCgrSgQMHHH2Y14gRIzR+/HgNHTo0y/93bdq00ezZsw0m+58dO3bkWpadcHh27969FRcXpxdffNGxc115wzDyTvb777+rXLlyud5evnx5/f7774WSxV0or3Idu7QRzo0TNsJFihRR5cqVHfEtTF6GDBmiIkWKKC4uLsskdY888oi+/PJLg8m8x+zZs/X111+rYsWKqlWrlho3bpzlYtovv/yiHj16qGLFivL19ZWPj0+WC67M1q1bczxvITIyUlu3bjWQyHvdddddmjhxYq63T548+YrPEbmWmjRpos8//9xz/dKHw/nz53sGlTFh165dSktLkyS9/vrreuONN/Taa6/Jz89Pzz77rL766isNGjRICQkJxjJKUvHixbVu3TqFhYUpODg4x4sTfPfddzkO2HHTTTfpt99+M5Do4nxml/bIfvjhh7rjjju0f/9+/ec//1FaWpr27duntWvXOuZnuHHjRr333nt68skn1alTJz344INZLk7gDcPIO1mVKlW0bdu2XG/funVrtuHvrxX2SF2lSxvhpUuX5ni7UzbC3rCnYtWqVVq5cqVuvvnmLMtr1KhhbA4kb9OpUyfTEfLkDd8UeoOUlBSlp6dnW56Wlqbz588bSOS9XnrpJTVt2lTNmjXT0KFDVbt2bVmWpf3792v69OmKiYnRN998YzqmJk6cqPbt2ysmJkbp6emaOXOmYmJitHnzZq1fv95YrsunN4iLi/N8OCxatKjnG+EePXqoWbNmxveohIWF6eeff8719sqVKxdimpyFhITo+PHjCgsLy7J8165dqlSpkpFMl89nNnHiRE2fPl0DBgxQiRIlNHPmTIWFhen//u//VKFCBSP5/ig0NDTXQzidwhuGkXeybt26aejQoapVq1a2c8K/++47DRs2TD179iyULBSpq+QtG+HZs2fr8OHDqlixoqpUqZJtcAkTx67/0blz57Lsibrk9OnT8vf3N5AoZ6mpqTmeHOqEjfBLL71kOkKeNm7cqA0bNqhhw4amo3i122+/3fPN/+XmzJmjW2+91VAq7xQREaGvvvpKffv2Vbdu3Tzl3rIs1a5dW6tWrXLECf4tW7ZUdHS0Jk2apHr16mnVqlVq3LixtmzZonr16hnLFR4eru3bt6t06dIqV66cTp8+rSpVqqhy5cr65ptv1KBBAx09etQRH2yrVq2a55c3Tjhqo1u3bnruuef08ccfy+VyKTMzU5s2bSrUD4Z/dPkcZrGxserQoYMkyc/Pz3No6ZAhQ9SmTRuNGTPGSMbLzZgxQyNGjNDcuXOzzbXnFEz3cnVGjhyp1atXq2HDhrr77rtVp04dz2fv1atX6/bbb9fzzz9fKFkoUlfJWzbCTt9TIUmtWrXSokWLPMM3X9qITJkyxRF79Q4dOqTHH39cmzdvzrL80mAYTtgIX/Ltt99q//79kqRbbrnFMXNIecM3hd5g/PjxateunaKjo9W2bVtJF0eA2r59u1atWmU4nfdp1qyZ9u3bp927d2eZC9AphT8tLU3/93//pxdffFHz5s0zHSeLp59+2vPF3F133aXPPvtMjRo1Up8+fTRkyBAtWbJEO3bsyHfqg8Lwx5EN09LStGvXLk2bNk0TJkwwlCqriRMnasCAAQoNDVVGRoYiIiKUkZGhxx57TP/85z+NZGrTpo2WLVumkJAQlSxZUklJSZKkSpUqae/evapXr57Onj3rmYrBtEceeUTJycmqVq2aAgMDs5UU05MaSxcnkb20ftm7d2+W2zhSI38BAQFat26dZw7XS3vla9asqfHjx2vIkCGF9gU8o/YVIKduhL3F3r171bZtWzVu3Fhr167VAw88oH379un06dPatGmTqlWrZjRfixYt5OvrqxEjRuR4WJoTRso7efKkunXrpqioKIWEhEiSzp49q7vuuksffvih8cmXV61apalTpzr6m0JvsXv3br3yyivavXu3ihYtqvr162vkyJGqUaOG6WjXhdTUVKWmpjpmSPng4GDt3r072yFfTpKamqr09HTPkQUfffSRNm3apBo1auiJJ55wxOT0Ofn888/1yiuvKCoqysjrJyYmZhtpMz4+Xt99952SkpLUqFEjo3/XQ4YM0fjx41WsWDF169ZNzZs319NPP61x48bptdde04MPPqivvvpKjRs3dsRgE5fmWstNr169CikJbgQUqWvEaRvhS5x8WJp08UP/v/71ryxDtA8YMMARx14XK1ZM3377rZFJba/UI488oiNHjmjRokVZJqjr1auXqlevrg8++KDQM5UsWTJL6Tx37pznw5YTvynEjeftt9/Wzp071axZM3Xv3l3PP/+8pk6dqvT0dLVp00YffvihSpcubTRjr1691LBhQw0ZMsRojvxcuHBBe/bsybadcblc6tixo8FkuTt8+LAaNGigc+fOGXn9yycKvnzvjxOdPHlS58+fV5UqVTxHjGzevFk1atTQP//5z1zn6ELOmO7lz9m2bZtuvfXWXAepSklJ0fLly9W1a9drnoUiVQC8YSN88OBB9e3b1/GHpeW2EZakBx54wFCqi2677TZNnz5dLVu2NJojL8HBwVq9erVuu+22LMu3bdume+65R2fPni30TPl9O3g5vim078KFC9mGIGYeqSs3YcIETZgwQS1atNDOnTvVtWtXffLJJxo8eLDcbrdmzZql+++/X//+97+N5hw/frymTp2qtm3b6tZbb812nuugQYMMJfufL7/8Uj179sxxdDknbGf+ONeWZVk6fvy4Ro8ere+//167d+82kis4OFjffPON6tSpI7fbrV9++cX40QO56dmzpyIjI9W6dWvjR4lc7vK9evnNqeaE9WNu0708/vjjTPdyBS7/8kG6+DvdvXu3wsPDJV0cIbhixYqFss7hHKmrdPlG+P3339fGjRv1ySefaOzYsZ6N8D//+U/jG+E+ffrI19dXn332mWNHS/vyyy/Vo0cPnT59Ott5NE7YCL/88st69tlnNXHiRNWrVy/b3hQnrJwzMzNzPHymSJEi2YppYbm8HDl1I+xtkpOT9eyzz2rx4sU6depUtttN/614kwULFujNN9/Uo48+qh07dqhp06ZavHixZ5L1unXr6oknnjCcUnrzzTcVEhKib7/9Vt9++22W21wulyOK1MCBA9WlSxeNGjUqzzleTAkJCcm27bMsS6Ghofrwww8NpZLatWunu+66y3MUwUMPPSQ/P78c77t27drCjJaNn5+fJk+erH79+qlSpUpq3bq1Z51u8vDDkiVLej5Y5/R7lpz1xfHl071c+r1LF48qGTp0KEUqH3/8jJjTPqHC2k/EHqmrVKNGDY0dOzbXjfAXX3yhJ554wvjw3d5wWFqNGjV0zz33OHYj7Hb/b9q1y1fSTlo5P/jggzp79qw++OADVaxYUZL0008/qXv37ipZsqTx2dL79++v9evXKzY2VhUrVnTMRtjbDBgwQOvWrdO4cePUo0cP/etf/9JPP/2kuXPnavLkyerevbvpiF7D399fhw8f9kzI6+/vrz179qhWrVqSLv79hIWFZdvrh+yCgoK0a9cux35J8sdh4t1ut8qWLavq1avL19fc98rnz5/XwoULFRsbq6lTp6p///45jmArXRyK3Al++uknff3111q/fr3Wr1+vgwcPqkKFCvrxxx+N5Fm/fr3nPOb8pgNo3bp1IaXKXfny5bVy5Uo1aNBAJUqUUHR0tMLDw3XkyBHVr1/fM6AHcuZ2u3XixAnPHqnLf4YSe6S8SlxcnOdQryZNmsjX1zfLmPb169fX8ePHTcXziIiIMDaZ35X65ZdfNHToUEeWKCnrfClONXv2bD3wwAOqWrWq54NhXFyc6tWrp3fffddwOnlGHLt8Izx16lTPHCSmNsLe5tNPP9WiRYsUGRmpPn36qFWrVqpevbqqVKmi9957jyJlQ1paWpbRnfz8/LLs1fX19TX2JcnQoUOv6H4ul8sR32A//PDDioqKcmyRuvQBOiYmRnFxcUpNTdWZM2c8g0SZOny8aNGinr2eO3bs0Msvv6yQkBDPN+pOPIKkZMmSKl26tEqWLKmQkBD5+voaPRzx8nLUunVrbdiwQXPnzlVsbKyWLFmiSpUq6Z133nHMYC3eMt0L8keRukpO3ghffpywNxyW5g0b4bNnz+rNN9/0DC0eERGhvn37OmZG99DQUO3cuVNr1qzxZKxTp47atWtnOFlWTtsI5+TyD1uXM32unnRxY3vpm7egoCDPIB0tW7bUk08+aTKaV4qJidGJEyckXdzD/P3333u+ETb5BdQfh+veuXOn0tPTPXvLDh48KB8fH8fMHTZ79mx16dJFGzZsyHE7Y/rwwyNHjqhz587as2ePXC5XtqLihKMK1q1bpzfffFPTp0/XoUOHJF08WmPw4MHq16+f4XTS888/r6ioKO3atUt16tRR69atNWLECN15552OGWhi6dKl6tGjh7p3765du3YpJSVFkpSQkKCJEydqxYoVhhM6f7oXb+CU9TaH9l0lt9uttWvXqlSpUpKkO+64Q4sXL9bNN98s6eIv8+677zaygna73TkegnY5Jx2WlpycrC5duqhs2bKO3Ajv2LFD9913nwICAnT77bdLkrZv367z5897Jsd0gjVr1mjNmjU5Dtjx1ltvGUp1UU4b4cjISEdthI8cOaKHHnpI3333nWM/bNWvX1+vvfaaWrdurXbt2qlhw4Z69dVXNWvWLE2ZMoU9ezZcWk/mtCm8tNwJ68hp06YpKipKCxcu9PytnDlzxrNH8plnnjGaT7p4HtcTTzyhgIAAlS5dOsv2xuVy6ciRIwbTSR07dpSPj4/mz5+vsLAwbd26VadPn9YzzzyjV199Va1atTKaT7o4qfrUqVM1cOBANW/eXJK0ZcsWzZ49W0OGDNHYsWON5rt0OOSQIUPUuXNn1axZ02ienDRq1EhDhgxRz549sxzytWvXLrVv397z4dukffv2qU2bNo6d7sXpnLTepkhdJSf9Mv/o8uOEjx07ptDQ0GxDRWZmZiouLs4Ro6U5fSN86fCpefPmeY6nT09PV79+/XTkyBF9/fXXRvNJ0pgxYzR27Fg1adIkx0FFTJ8j5Q0b4T9+2Nq2bZtOnTrlqA9b06dPl4+PjwYNGqTVq1erY8eOsixLaWlpmjZtmp5++mnTEb3GlZ6/WqVKlWucJG+VKlXKcYL3vXv36p577tHPP/9sKNn/lC9fXoMGDdKIESOynFPqFGXKlNHatWtVv359BQcHa9u2bapVq5bWrl2rZ555JtseQBPKli2rWbNm6dFHH82y/IMPPtDAgQONH6IfHR2t9evXKyoqShs2bJCfn5/nC7HIyEhHrNMDAwMVExOjqlWrZjv/KCIiQhcuXDCaLy0tTffdd58mTZqkr776ypHTvTido9bbFq7KsWPHruhimtvttn755Zdsy3/77TfL7XYbSJRduXLlrAkTJlgZGRmmo+QoICDA2r9/f7bl+/bts4oWLWogUXbly5e3Fi1aZDpGrnbv3m3NnDnTeuihh6wyZcpYFStWtB599FFr7ty51oEDB0zHsyzLskqXLm1FR0dblmVZQUFB1vfff29ZlmWtWbPGatiwoclolmVZVmpqqtWmTRvr4MGDnmXHjh2zli5d6smNKxMdHW1rfbN3714rLS3tGibKXfHixa1169ZlW7527VqrePHihR8oByVLlrQOHz5sOkauQkJCrCNHjliWZVnh4eHW2rVrLcuyrMOHDztmHR4cHJzlb/uSAwcOWMHBwYUfKB+7d++2evXqZfn6+jrms0RYWJj11VdfWZZ18e8mNjbWsizLWrhwoVWnTh2T0TzKlCmT4+8Z+XPaett5Xxl5kT179ig0NFRVqlTJ9yJd3JWbnp5uJKuVyyRvSUlJCggIMJAou9TUVD3yyCOO/CZTunguSlxcXLbl8fHxKlGihIFE2aWmpuqOO+4wHSNXDRo00KBBg7Rs2TL9+uuvWrFihfz8/DRgwIAsQ8CalJGR4fl9lilTxvNNf5UqVXTgwAGT0SRdHMp+z549WZZVqVJFnTt3Vv369Q2l8k6NGjXKcfj43DRv3jzHdUBheOihh9SnTx8tW7ZMP/74o3788UctXbpUffv2VefOnY1k+qNevXrpo48+Mh0jV3Xr1lV0dLQkqWnTppoyZYo2bdqksWPHes45NK1Hjx45TpfyxhtvOGIQGcuytHPnTk2bNk0PPPCA7rrrLr377ruqV6+e8cPvL+nfv7+efvppbd26VS6XSz///LPee+89DRs2zDHnkP7tb3/Tm2++aTqGV3LaepvBJq5Co0aNdOLEiSs+Sb558+ZZJgwrDJdGfXK5XHrxxRezjBKTkZGhrVu3qmHDhoWWJy+XNsLPP/+86Sg5euSRR9S3b1+9+uqrnrKyadMmDR8+PNthGKb069dP77//vl588UXTUXJkWZZ27dqlqKgoRUVFaePGjUpMTFT9+vUdMSSt9L8PW2FhYZ4PW35+fnrjjTcc82Hr0kZ48uTJpqN4Ncuysq0X82JyCPQ5c+Zo2LBheuyxx5SWlibp4mBGffv21SuvvGIs1+UyMjI0ZcoUrVy5UvXr1892nuu0adMMJbvon//8p86dOydJGjt2rO6//361atVKpUuXdlQBfPPNN7Vq1So1a9ZMkrR161bFxcWpZ8+eWUZyNPHzLFWqlJKSktSgQQO1bt1a/fv3V6tWrRQSElLoWXIzYsQIZWZmqm3btkpOTtadd94pf39/DRs2TAMHDjQdT9LF0wLeeustrV69OscJtk3/reSlXbt2OnLkiLHTLZy23uYcqavgdrv197///Yp/ma+//rpiYmIK9cPYpdFf1q9fr+bNm2eZ5M/Pz09Vq1bVsGHDHDGHz6BBg7Ro0SI1aNDAkRvh1NRUDR8+XHPmzPHsWSxSpIiefPJJTZ482diQpZdvWDMzM7Vw4ULVr1/fkT/DkiVLZtkIR0ZGOm4jvHLlSp07d06dO3fW4cOHdf/99+vgwYOeD1tt2rQxHVEDBw7UokWLVKNGDTbCVyEyMtL20NLvv/++0XMYzp07p9jYWElStWrVsv3uTcprtDGXy2V8MtmcnD59WiVLlnTMEONXOmKbqZ/n559/rlatWjlipN/8pKam6vDhw0pKSlJERISKFy9uOpKHN/6tXPKvf/1Lv/32m1566SUjr++09TZF6io47ZeZlz59+mjmzJmOXvl5y4olOTk5yweZKy3S14rTN7yX86aN8OW86cOWE37PeTG9EQYAoKBQpAAAAADAJmee1Q8AAAAADkaRAgAAAACbKFLXQEpKikaPHq2UlBTTUXLk9HyS8zM6PZ9ExoLg9HyS8zM6PV9OnJ7Z6fkk52d0ej6JjAXB6fkkMhYEk/k4R+oaSExMVHBwsBISEhx5Ur3T80nOz+j0fBIZC4LT80nOz+j0fDlxeman55Ocn9Hp+SQyFgSn55PIWBBM5mOPFAAAAADYRJECAAAAAJt8TQcwLTMzUz///LNKlChRYHPEJCYmZvmv0zg9n+T8jE7PJ5GxIDg9n+T8jNcin2VZ+v3331WxYkVJYh3uQE7P6PR8EhkLgtPzSWQsCAWd7/JtjNud9z6nG/4cqR9//FGhoaGmYwAAbIqPj5ck1uEAgAIXHx+vm2++Oc/73PB7pEqUKCFJ+mFnVQUVd+6Rjg/VrGc6AgA4QrrStFErPOtvSWqpDvJVEYOp8vafg9+ZjpCnhx94yHSEfGUciDUdIV/uwKKmI+Qp81yy6QjXB7eP6QT5y8wwncBr5bSNyc0NX6QuHQoSVNytoBLOLVK+Lud+QACAQvX/j6O4/FA+XxVx9HrSydsXSfL18TcdIV8uB/9+L3G7/ExHyFOmK810hOuDywuKlMvZ6xxHy2Ebkxt+ygAAAABgE0UKAAAAAGyiSAEAAACATRQpAAAAALCJIgUAAAAANlGkAAAAAMAmihQAAAAA2ESRAgAAAACbKFIAAAAAYBNFCgAAAABsokgBAAAAgE0UKQAAAACw6ZoXqaioKLlcLp09e/ZavxQAAAAAFIoCL1KRkZEaPHhwQT8tAAAAADiGIw/tS01NNR0BAAAAAHJVoEWqd+/eWr9+vWbOnCmXyyWXy6Vjx45Jkr799ls1adJEgYGBuuOOO3TgwAHP40aPHq2GDRtq/vz5CgsLU0BAgCTp7Nmz6tevn8qWLaugoCC1adNG0dHRWV5z+fLlaty4sQICAhQeHq4xY8YoPT29IN8WAAAAAGRRoEVq5syZat68ufr376/jx4/r+PHjCg0NlSS98MILmjp1qnbs2CFfX189/vjjWR57+PBhLV26VMuWLdPu3bslSV26dNHJkyf1xRdf6Ntvv1Xjxo3Vtm1bnT59WpK0YcMG9ezZU08//bRiYmI0d+5cLViwQBMmTMg1Y0pKihITE7NcAADeIdPKULrSJIl1OADAqAItUsHBwfLz81NgYKDKly+v8uXLy8fHR5I0YcIEtW7dWhERERoxYoQ2b96sCxcueB6bmpqqRYsWqVGjRqpfv742btyobdu26eOPP1aTJk1Uo0YNvfrqqwoJCdGSJUskSWPGjNGIESPUq1cvhYeH6+6779a4ceM0d+7cXDNOmjRJwcHBnsulogcAcL6j+l4btUKSFBoayjocAGCMb2G9UP369T3/rlChgiTp5MmTqly5siSpSpUqKlu2rOc+0dHRSkpKUunSpbM8z/nz5xUbG+u5z6ZNm7LsgcrIyNCFCxeUnJyswMDAbDlGjhypoUOHeq4nJiayIQYALxGm2qqkMG3UCsXHx0sS63AAgBGFVqSKFCni+bfL5ZIkZWZmepYVK1Ysy/2TkpJUoUIFRUVFZXuukJAQz33GjBmjzp07Z7vPpfOs/sjf31/+/v524wMAHMDt8pGvdXF7EhQUZDgNAOBGVuBFys/PTxkZGVf9PI0bN9aJEyfk6+urqlWr5nqfAwcOqHr16lf9egAAAABwpQq8SFWtWlVbt27VsWPHVLx48Sx7nexo166dmjdvrk6dOmnKlCmqWbOmfv75Z33++ed66KGH1KRJE40aNUr333+/KleurIcfflhut1vR0dHau3evxo8fX8DvDAAAAAAuKvB5pIYNGyYfHx9FRESobNmyiouL+1PP43K5tGLFCt15553q06ePatasqW7duumHH35QuXLlJEn33nuvPvvsM61atUq33XabmjVrpunTp6tKlSoF+ZYAAAAAIAuXZVmW6RAmJSYmKjg4WGcOhiuohCPnJ5Yk3VuxoekIAOAI6VaaorRcCQkJki6OGBupB+XrKpLPI81Z+fNu0xHy1KFdV9MR8pWx/5DpCPly5zDIlZNknjtnOsL1we1jOkH+Mq/+NJsb1eXbmPzOxXVucwAAAAAAh6JIAQAAAIBNFCkAAAAAsIkiBQAAAAA2UaQAAAAAwCaKFAAAAADYRJECAAAAAJsoUgAAAABgE0UKAAAAAGyiSAEAAACATRQpAAAAALCJIgUAAAAANlGkAAAAAMAmX9MBnKLeZ73lLhpgOkauikz2MR0hT2EjtpiOAOAG5o6oKbePv+kYueoQEWw6Qp66b11jOkK+3mvR0HSE/FmW6QR5O3fOdIL8uZ39eUeSZGWaTpA/l8t0grw5/W/lCrFHCgAAAABsokgBAAAAgE0UKQAAAACwiSIFAAAAADZRpAAAAADAJooUAAAAANhEkQIAAAAAmyhSAAAAAGATRQoAAAAAbKJIAQAAAIBNFCkAAAAAsIkiBQAAAAA2UaQAAAAAwCaKFAAAAADYRJECAAAAAJsoUgAAAABgE0UKAAAAAGyiSAEAAACATYVWpCIjIzVw4EANHjxYJUuWVLly5TRv3jydO3dOffr0UYkSJVS9enV98cUXnsfs3btX7du3V/HixVWuXDn16NFDv/32W5bnHDRokJ599lmVKlVK5cuX1+jRowvrLQEAAAC4QRXqHqmFCxeqTJky2rZtmwYOHKgnn3xSXbp00R133KGdO3fqnnvuUY8ePZScnKyzZ8+qTZs2atSokXbs2KEvv/xSv/zyi7p27ZrtOYsVK6atW7dqypQpGjt2rL766qtcM6SkpCgxMTHLBQDgHTKtDKUrTZJYhwMAjHJZlmUVxgtFRkYqIyNDGzZskCRlZGQoODhYnTt31qJFiyRJJ06cUIUKFbRlyxatXr1aGzZs0MqVKz3P8eOPPyo0NFQHDhxQzZo1sz2nJN1+++1q06aNJk+enGOO0aNHa8yYMdmW3zxtrNxFAwryLReoIok+piPkKWzEFtMRANwAYq19Oqr92Za3iRguXx9/A4mujOvH46Yj5Kn71r2mI+TrvRYNTUfIX+F8pPrTMk6dNh0hf25nf96RJFmZphN4Pwf/raRbaYrSciUkJCgoKCjP+xbqHqn69et7/u3j46PSpUurXr16nmXlypWTJJ08eVLR0dFat26dihcv7rnUrl1bkhQbG5vjc0pShQoVdPLkyVwzjBw5UgkJCZ5LfHx8gbw3AMC1F6baaqkOkqT4+HjW4QAAY3wL88WKFCmS5brL5cqyzOVySZIyMzOVlJSkjh076uWXX872PBUqVMjzOTMzc/+mwN/fX/7+zv3WEgCQO7fLR77WxfV+ft8UAgBwLRVqkbKjcePGWrp0qapWrSpfX8fGBAAAAHADcuzw5wMGDNDp06f16KOPavv27YqNjdXKlSvVp08fZWRkmI4HAAAA4Abm2CJVsWJFbdq0SRkZGbrnnntUr149DR48WCEhIXK7HRsbAAAAwA2g0I6Zi4qKyrbs2LFj2ZZdPohgjRo1tGzZMlvP+cknn/yJdAAAAABw5di1AwAAAAA2UaQAAAAAwCaKFAAAAADYRJECAAAAAJsoUgAAAABgE0UKAAAAAGyiSAEAAACATRQpAAAAALCJIgUAAAAANlGkAAAAAMAmihQAAAAA2ESRAgAAAACbfE0HcIrQLy35FrFMx8hVQpjLdIQ8/fj8HaYj5OvmiZtNRwBwjbiTzsntTjcdI1cZYTebjpCnd245ZzpCvmIn1DQdIV8l95tOkLcynx00HSFfVpLz/190+fmZjpCvzPMXTEfIk5WeZjpCHlzSFVYC9kgBAAAAgE0UKQAAAACwiSIFAAAAADZRpAAAAADAJooUAAAAANhEkQIAAAAAmyhSAAAAAGATRQoAAAAAbKJIAQAAAIBNFCkAAAAAsIkiBQAAAAA2UaQAAAAAwCaKFAAAAADYRJECAAAAAJsoUgAAAABgE0UKAAAAAGyiSAEAAACATRQpAAAAALDJ8UUqJSVFgwYN0k033aSAgAC1bNlS27dvlyRFRUXJ5XJpzZo1atKkiQIDA3XHHXfowIEDhlMDAAAAuJ45vkg9++yzWrp0qRYuXKidO3eqevXquvfee3X69GnPfV544QVNnTpVO3bskK+vrx5//PFcny8lJUWJiYlZLgAA75BpZShdaZLEOhwAYJSji9S5c+f073//W6+88orat2+viIgIzZs3T0WLFtWbb77pud+ECRPUunVrRUREaMSIEdq8ebMuXLiQ43NOmjRJwcHBnktoaGhhvR0AwFU6qu+1USskSaGhoazDAQDGOLpIxcbGKi0tTS1atPAsK1KkiG6//Xbt37/fs6x+/fqef1eoUEGSdPLkyRyfc+TIkUpISPBc4uPjr1F6AEBBC1NttVQHSVJ8fDzrcACAMb6mAxSEIkWKeP7tcrkkSZmZmTne19/fX/7+/oWSCwBQsNwuH/laF9f5QUFBhtMAAG5kjt4jVa1aNfn5+WnTpk2eZWlpadq+fbsiIiIMJgMAAABwI3P0HqlixYrpySef1PDhw1WqVClVrlxZU6ZMUXJysvr27avo6GjTEQEAAADcgBxdpCRp8uTJyszMVI8ePfT777+rSZMmWrlypUqWLGk6GgAAAIAblOOLVEBAgGbNmqVZs2Zluy0yMlKWZWVZ1rBhw2zLAAAAAKAgOfocKQAAAABwIooUAAAAANhEkQIAAAAAmyhSAAAAAGATRQoAAAAAbKJIAQAAAIBNFCkAAAAAsIkiBQAAAAA2UaQAAAAAwCaKFAAAAADYRJECAAAAAJsoUgAAAABgE0UKAAAAAGzyNR3AKeLbu+Qu6jIdI1d1pv9iOkKeMoOKmo6Qr7S2t5qOkC/fNd+ajgB4pfS4nyRXEdMxcuUuGWE6Qp4yMzJMR8hXtVE7TUfI1/IjG01HyNODH7Q0HSFfVkqK6Qj5u3DBdAJcS5Z1xXdljxQAAAAA2ESRAgAAAACbKFIAAAAAYBNFCgAAAABsokgBAAAAgE0UKQAAAACwiSIFAAAAADZRpAAAAADAJooUAAAAANhEkQIAAAAAmyhSAAAAAGATRQoAAAAAbKJIAQAAAIBNFCkAAAAAsIkiBQAAAAA22SpSkZGRGjx48DWKAgAAAADegT1SAAAAAGCT0SKVmppq8uUBAAAA4E+xXaQyMzP17LPPqlSpUipfvrxGjx7tuS0uLk4PPvigihcvrqCgIHXt2lW//PKL5/bRo0erYcOGmj9/vsLCwhQQECBJWrJkierVq6eiRYuqdOnSateunc6dO+d53Pz581WnTh0FBASodu3aev311z23paam6h//+IcqVKiggIAAValSRZMmTfozPwsAAAAAuCK+dh+wcOFCDR06VFu3btWWLVvUu3dvtWjRQm3btvWUqPXr1ys9PV0DBgzQI488oqioKM/jDx8+rKVLl2rZsmXy8fHR8ePH9eijj2rKlCl66KGH9Pvvv2vDhg2yLEuS9N5772nUqFGaPXu2GjVqpF27dql///4qVqyYevXqpVmzZum///2vFi9erMqVKys+Pl7x8fG55k9JSVFKSornemJiot0fAQDAkEwrQ+lKk8T6GwBglu0iVb9+fb300kuSpBo1amj27Nlas2aNJOm7777T0aNHFRoaKklatGiRbrnlFm3fvl233XabpIt7kBYtWqSyZctKknbu3Kn09HR17txZVapUkSTVq1fP83ovvfSSpk6dqs6dO0uSwsLCFBMTo7lz56pXr16Ki4tTjRo11LJlS7lcLs9z5GbSpEkaM2aM3bcNAHCAo/peR7VfkjzbGgAATLB9aF/9+vWzXK9QoYJOnjyp/fv3KzQ0NMuGLSIiQiEhIdq/f79nWZUqVTwlSpIaNGigtm3bql69eurSpYvmzZunM2fOSJLOnTun2NhY9e3bV8WLF/dcxo8fr9jYWElS7969tXv3btWqVUuDBg3SqlWr8sw/cuRIJSQkeC557b0CADhLmGqrpTpIUr5HIAAAcC3Z3iNVpEiRLNddLpcyMzOv+PHFihXLct3Hx0dfffWVNm/erFWrVum1117TCy+8oK1btyowMFCSNG/ePDVt2jTb4ySpcePGOnr0qL744gutXr1aXbt2Vbt27bRkyZIcX9/f31/+/v5XnBcA4Bxul498rYvboaCgIMNpAAA3sgIbta9OnTrZvh2MiYnR2bNnFRERkedjXS6XWrRooTFjxmjXrl3y8/PTf/7zH5UrV04VK1bUkSNHVL169SyXsLAwz+ODgoL0yCOPaN68efroo4+0dOlSnT59uqDeGgAAAABkYXuPVG7atWunevXqqXv37poxY4bS09P11FNPqXXr1mrSpEmuj9u6davWrFmje+65RzfddJO2bt2qX3/9VXXq1JEkjRkzRoMGDVJwcLDuu+8+paSkaMeOHTpz5oyGDh2qadOmqUKFCmrUqJHcbrc+/vhjlS9fXiEhIQX11gAAAAAgiwIrUi6XS8uXL9fAgQN15513yu1267777tNrr72W5+OCgoL09ddfa8aM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2ESRAgAAAACbKFIAAAAAYBNFCgAAAABsokgBAAAAgE0UKQAAAACwiSIFAAAAADYVWJGKjIyUy+WSy+XS7t27C+ppvS4DAAAAgOtfge6R6t+/v44fP666devq2LFjnlLzx8s333zjecz58+f10ksvqWbNmvL391eZMmXUpUsX7du3L8tzJycna+TIkapWrZoCAgJUtmxZtW7dWsuXL/fcZ9myZdq2bVtBviUAAAAAyMa3IJ8sMDBQ5cuXz7Js9erVuuWWW7IsK126tCQpJSVF7dq1U1xcnKZOnaqmTZvql19+0aRJk9S0aVOtXr1azZo1kyQ98cQT2rp1q1577TVFRETo1KlT2rx5s06dOuV53lKlSikxMbEg3xIAAAAAZFOgRSonpUuXzlauLpkxY4a2bNmiXbt2qUGDBpKkKlWqaOnSpWratKn69u2rvXv3yuVy6b///a9mzpypDh06SJKqVq2qW2+99VrHBwAAAIBsjA428f777+vuu+/2lKhL3G63hgwZopiYGEVHR0uSypcvrxUrVuj333+/qtdMSUlRYmJilgsAwDtYaenKPH9BkliHAwCMuuZF6o477lDx4sWzXC45ePCg6tSpk+PjLi0/ePCgJOmNN97Q5s2bVbp0ad12220aMmSINm3aZDvPpEmTFBwc7LmEhob+iXcFADAhYcU6/fzsJElSaGgo63AAgDHXvEh99NFH2r17d5bL5SzLuqLnufPOO3XkyBGtWbNGDz/8sPbt26dWrVpp3LhxtvKMHDlSCQkJnkt8fLytxwMAzAnucJcqThkpSYqPj2cdDgAw5pqfIxUaGqrq1avneFvNmjW1f//+HG+7tLxmzZqeZUWKFFGrVq3UqlUrPffccxo/frzGjh2r5557Tn5+fleUx9/fX/7+/jbfBQDACVxFfOUuGiBJCgoKMpwGAHAjM3qOVLdu3bR69WrPeVCXZGZmavr06YqIiMh2/tTlIiIilJ6ergsXLlzrqAAAAADgcc33SJ06dUonTpzIsiwkJEQBAQEaMmSIli9fro4dO2YZ/nzixInav3+/Vq9eLZfLJeniZLuPPvqomjRpotKlSysmJkbPP/+87rrrLr6VBAAAAFCornmRateuXbZlH3zwgbp166aAgACtXbtWEydO1PPPP68ffvhBJUqU0F133aVvvvlGdevW9Tzm3nvv1cKFC/X8888rOTlZFStW1P33369Ro0Zd67cAAAAAAFlcsyJVtWrVKxpIIjAwUOPHj9f48ePzvN/IkSM1cuTIgooHAAAAAH9agZ4j9frrr6t48eL67rvvCvJpr1j79u11yy23GHltAAAAADeOAtsj9d577+n8+fOSpMqVKxfU09oyf/584xkAAAAAXP8KrEhVqlSpoJ7KqzMAAAAAuP4ZHf4cAAAAALwRRQoAAAAAbKJIAQAAAIBNFCkAAAAAsIkiBQAAAAA2UaQAAAAAwCaKFAAAAADYRJECAAAAAJsoUgAAAABgk6/pAKZZliVJSs9MNZwkb5lWmukIebKsDNMR8uWyXKYj5MtlmU6Qt8z0C6Yj5MttOftvWZJcGSmmI+Qp87yzf8+X8l1af0tSusP/38xI9TEdIU/pXvB34/TtoCRZDv/bzvCCn6Hbcv53/N6wLXT6/4vp6c79Paf//5/d5duY3LisK7nXdezHH39UaGio6RgAAJvi4+MliXU4AKDAxcfH6+abb87zPjd8kcrMzNTPP/+sEiVKyOUqmD0WiYmJCg0NVXx8vIKCggrkOQuS0/NJzs/o9HwSGQuC0/NJzs94LfJZlqXff/9dFStWlCTW4Q7k9IxOzyeRsSA4PZ9ExoJQ0Pku38a43XnvObvhD+1zu935ts0/KygoyJH/w13i9HyS8zM6PZ9ExoLg9HyS8zMWdL7g4GDPv1mHO5fTMzo9n0TGguD0fBIZC0JB5rt8G5MX5x6gCAAAAAAORZECAAAAAJsoUteAv7+/XnrpJfn7+5uOkiOn55Ocn9Hp+SQyFgSn55Ocn9Hp+XLi9MxOzyc5P6PT80lkLAhOzyeRsSCYzHfDDzYBAAAAAHaxRwoAAAAAbKJIAQAAAIBNFCkAAAAAsIkiBQAAAAA2UaQAAAAAwCaKFAAAAADYRJECAAAAAJsoUgAAAABg0/8DbGxuQQB+xhYAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['three men on horses while a race.']\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  7%|▋         | 9/128 [00:00<00:00, 148.03it/s]\n",
      "/usr/local/lib/python3.10/site-packages/IPython/core/pylabtools.py:170: UserWarning: There are no gridspecs with layoutgrids. Possibly did not call parent GridSpec with the \"figure\" keyword\n",
      "  fig.canvas.print_figure(bytes_io, **kw)\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1sAAAHbCAYAAAA9E4D0AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAVfBJREFUeJzt3Xl4E+XC/vE7aWlY2rRQEAqUtsgiWBYRZJNFRHFXUFRUFEHUo0cURKHIvhVZRFxeBRQBFRGRVzwosim8sgiyFBSQpSytSuVQji1rC838/uBHDrEtsk2fKf1+risXzSRN7iQlT+7MzDMuy7IsAQAAAAAuKbfpAAAAAABwOaJsAQAAAIANKFsAAAAAYAPKFgAAAADYgLIFAAAAADagbAEAAACADShbAAAAAGADyhYAAAAA2ICyBQAAAAA2oGwBAAAAgA0oWwAAAABgg2DTAQAAhcumTZvyXO5yuVS8eHFVqVJFHo+ngFMBAOA8LsuyLNMhAACFh9vtlsvlyvfyYsWK6YEHHtDEiRNVvHjxAkwGAICzsBkhAOC8/O///q+qV6+uSZMmKSkpSUlJSZo0aZJq1qypGTNm6P3339e3336r/v37m44KAIBRrNkCAJyX6667TsOGDVO7du0Cli9YsEADBgzQmjVr9MUXX+jFF19UcnKyoZQAAJjHmi0AwHn56aefFBMTk2t5TEyMfvrpJ0lS/fr1tW/fvoKOBgCAozBBBoACs2TJEi1ZskT79++Xz+cLuGzKlCmGUuF8XXXVVRo1apQmTZqkkJAQSdKJEyc0atQoXXXVVZKk3377TeXLlzcZEwAA4yhbAArEkCFDNHToUDVs2FBRUVFnnWABzvb222/rrrvuUuXKlVW3bl1Jp9Z25eTkaN68eZKkXbt26ZlnnjEZEwAA49hnC0CBiIqK0ujRo9W5c2fTUXAJHDp0SB9//LG2b98uSapZs6YeeughhYWFGU4GAIBzULYAFIjIyEitWbNGV155pekoAAAABYKyBaBA9OnTR6GhoRowYIDpKLgEduzYoe+++y7P/e8GDhxoKBUAAM5C2QJQIJ5//nlNnz5ddevWVd26dVWsWLGAy1977TVDyXC+Jk+erH/84x8qW7asKlSoELD/ncvl0vr16w2mAwDAOShbAArEDTfckO9lLpdL3377bQGmwcWIiYnRM888oz59+piOAgCAo1G2ABRp11xzTZ4zI7pcLhUvXlzVqlVTly5dzloWixqv16ukpCRVrVrVdBQAgCFffvnlOV/3rrvusjGJs1G2ABRpCQkJeuedd1SnTh1dd911kqQff/xRmzZtUpcuXbRlyxYtWbJEc+bM0d133204rTN069ZNjRo10tNPP206CgDAELfbHXDe5XLpzFpx5heZOTk5BZbLaTjOFoACs3btWs2aNUspKSnKzs4OuGzOnDlGMh04cEAvvvhirok7hg8frr1792rhwoUaNGiQhg0bRtn6/6pVq6YBAwbohx9+UJ06dXLtf9ejRw9DyQAABeXMyZEWL16sPn36aOTIkWratKkkadWqVerfv79GjhxpKqIjsGYLQIGYOXOmHn30UbVr104LFy7UzTffrO3bt+uPP/5Q+/bt9cEHHxjJFR4ernXr1qlatWoBy3fu3Klrr71WGRkZ+uWXX9SoUSMdOnTISEaniYuLy/cyl8ulXbt2FWAaAIBp8fHxevfdd3X99dcHLP/+++/15JNPauvWrYaSmceaLQAFYuTIkRo/fryeffZZhYWFacKECYqLi9NTTz2lqKgoY7mKFy+ulStX5ipbK1euVPHixSWd+vbu9M+Qdu/ebToCANjiyJEjGjVqlJYsWZLnoS34MilvycnJioiIyLU8PDxce/bsKfA8TkLZslmDBg3O6/oul0tffvmlKlWqZFMiwIzk5GTdfvvtkqSQkBAdOXJELpdLPXv2VJs2bTRkyBAjuZ577jk9/fTTWrdunRo1aiTp1D5b7733nvr16ydJWrBggerXr28kHy4vjAkXj2O8wU5PPPGEli1bps6dOysqKirPCZSQW6NGjdSrVy99+OGHKl++vCTpjz/+0EsvveTfH7ogbdq06bx/p3bt2goOvvTViM0IbeZ2u/Xiiy8qNDT0b69rWZZGjRqlLVu2MMsXLjuVK1fW/PnzVadOHdWtW1cJCQnq1KmTVq1apVtuuUUZGRnGsn388cd66623tG3bNklSzZo19dxzz+mhhx6SJB07dsw/O2FR1atXLw0bNkylSpVSr169znpdjpmWP8aEi8Mx3mC3iIgIffXVV2revLnpKIXKzp071b59e23fvl3R0dGSpNTUVFWvXl1ffPFFrq1H7OZ2u3NN2PF319++fbst77WULZu53W6lpaXpiiuuOKfrh4WFaePGjQysuOw89NBDatiwof9D+5tvvqm7775bixYtUoMGDYxNkIFzc8MNN+h///d/FRERwTHTLgJjwsXhGG+wW1xcnL7++mvVqlXLdJRCx7IsLVq0SL/88oskqVatWmrbtq2RtYNut1tr1qxRuXLl/va6lmUpPj5emzZtomwVRnv37lWVKlXO+Q8tNTVVFStWVFBQkM3JgIJ18OBBHT9+XBUrVpTP59Po0aO1cuVKVa9eXf3791fp0qWN5svOzs5zs6QqVaoYSoTLEWPCxeEYb7DbRx99pLlz52ratGkqWbKk6Ti4QGd+QXgubrvtNr3//vu27ENO2QJQpO3YsUNdu3bVypUrA5ZbliWXy1Wkjw0COA3HeIPdrrnmGiUnJ8uyLMXGxuY6tAWbquZvyZIl+U4sMmXKFEOpzGOCjAJw4MABHTlyRDExMf5lmzdv1tixY3XkyBHdc889/n1DgMvd/v3783wjrlu3rpE8Xbp0UXBwsObNm8fO0OeI2bouDmPCheMYb7DbPffcYzpCoTRkyBANHTpUDRs2dPxYevLkSR0/fvyc9p29FFizVQA6deqkihUraty4cZJOfdi86qqrVLFiRV155ZWaP3++3n//fXXu3NlwUsA+69at02OPPaatW7fm2mHV5BqkUqVKad26dbrqqquM3H9h1KlTp7PO1vX8888bSlY4MCZcOI7xBjhTVFSURo8e7aj3rX/9619KT09Xly5d/MtGjBihYcOG6eTJk2rTpo0+/fRT23djYM1WAfjhhx80depU//np06erTJkySkpKUnBwsMaOHau3337bUX+gwKXWtWtX1ahRQ++//77Kly/vmG+9ateurQMHDpiOUajMnz+f2bouAmPCheMYbygIf/75p2bPnq3k5GS99NJLKlOmjNavX6/y5ctzGIZ8ZGdnq1mzZqZjBHjttdd03333+c+vXLlSAwcO1NChQ1WrVi298sorGjZsmO0z6LptvXVIktLS0hQbG+s//+2336pDhw7+ufzvuusu7dixw1A6oGDs2rVLo0ePVuPGjRUbG6uYmJiAkymvvvqqXn75ZS1dulTp6enKzMwMOCG30qVLq0yZMqZjFFqMCYBzbdq0STVq1NCrr76qsWPH6s8//5QkzZkzRwkJCWbDOdgTTzyhGTNmmI4RYPPmzQEFcPbs2brpppv0yiuvqEOHDho3bpz+9a9/2Z6DNVsFwOv16s8///R/oFyzZo26devmv9zlcikrK8tUPEfLycnR1KlT8903hCmmC48bb7xRGzduLPBjbfydtm3bSjqV70xMkJG/YcOGaeDAgczWdYEYEy4cY8L5+/DDD/Xuu+9q9+7dWrVqlWJiYvT6668rLi5Od999t+l4jtOrVy916dJFo0ePVlhYmH/5bbfdxr6UZ3H8+HFNmjRJixcvVt26dXPtT2ni+IuHDh1SZGSk//zy5cvVsWNH//mrr75av//+u+05KFsFoEmTJnrjjTc0efJkzZkzR4cOHVKbNm38l595ADgEev755zV16lTdfvvtio+Pd8ymZzh/7733nh577DH9/PPPio+Pz/VGfNdddxnJ9d133xm538Js3LhxSk5OVvny5Zmt6wIwJlw4xoTz884772jgwIF64YUXNGLECP+XRxEREXr99dcpW3n48ccfNXHixFzLK1WqpLS0NAOJCodNmzapfv36kqSff/454DJT/08rVaqkrVu3qkqVKjp8+LA2btyo8ePH+y9PT08vkC8MKVsFYNiwYbrxxhv10Ucf6eTJk+rXr1/AzngzZ85Uq1atDCZ0rpkzZ2rWrFm67bbbTEfBRVq1apVWrFih+fPn57rM5Bok/u+dP2brujiMCReOMeH8vPnmm5o8ebLuuecejRo1yr+8YcOG6t27t8FkpyY7OduHcFOTnXg8njw3Id++ffs5HSC3qHLiF5cdO3bUCy+8oH79+unrr79WhQoV1KRJE//la9euVc2aNW3PQdkqAHXr1tXWrVu1YsUKVahQQY0bNw64/MEHH1Tt2rUNpXO2kJAQx212hgvz3HPP6ZFHHtGAAQNUvnx5o1k2bdqk+Ph4ud1ubdq06azXNTUlvZMNGjTIdIRCjTHhwjEmnJ/du3frmmuuybXc4/HoyJEjBhL91wsvvBBw/sSJE9qwYYO++eYbvfTSS2ZC6dRWFkOHDtWsWbMknfoyMCUlRX369NG9995rLFdhsXPnTiUnJ6tly5YqUaKEf5N8EwYOHKjffvtNPXr0UIUKFfTRRx8FHCD+k08+0Z133ml7DqZ+h6ONGzdOu3bt0ltvvWV8c5HSpUufc4aDBw/anKbwCQsLU1JSkq688krTUeR2u5WWlqYrrrhCbrdbLpcr13T0ktk1bk7HbF0wwUljwvlMoOP1em1Mkr/atWsrMTFRd999t8LCwrRx40ZVrVpVb775pj744ANHbvL79ttva+3atfrggw+M3H9GRobuu+8+rV27VocOHVLFihWVlpampk2b6uuvv1apUqWM5HK69PR03X///fruu+/kcrm0Y8cOVa1aVV27dlXp0qX9h7ooilizVUBOnjyp8ePH65NPPtH27dslSTVq1NBDDz2k559/Ptc+Dzhl+fLl+u677zR//nxdffXVuZ6nOXPmFFiW119/3f9zenq6hg8frnbt2qlp06aSTm0mt2DBAg0YMKDAMhUmHTp00HfffeeIsrV7927/5iBMJX3+Nm3apLZt2yo8PFx79uxR9+7dVaZMGc2ZM0cpKSmaPn266YiOx5hwYZw0JkRERJxz4TP1pU2vXr307LPP6vjx47IsS2vWrNEnn3yixMREvffee0Yy/Z1bb71VCQkJxspWeHi4Fi1apBUrVmjjxo06fPiwGjRo4J9MCXnr2bOnihUrppSUFNWqVcu//IEHHlCvXr2Ml61NmzYFvNcW5FYrlK0CcOzYMd10001atWqV2rZtq5YtW0qStm7dqj59+ujLL7/UwoULVbx4ccNJnSciIkLt27c3HUOS9Nhjj/l/vvfeezV06FD985//9C/r0aOH3nrrLS1evFg9e/Y0EdHRatSooYSEBC1fvlx16tTJ9SGpR48eBZblzKnm9+7dq2bNmvmn3T7t5MmTWrlypdFp6U87fvy4o94fmK3r4jAmXDgnjQln7qOyZ88e9e3bV126dAn4Am7atGlKTEw0FVFPPPGESpQoof79++vo0aN66KGHVLFiRU2YMEEPPvigsVxnM3v2bEccWqJ58+b+Ywmenv4d+Vu4cKEWLFigypUrByyvXr269u7dayjVf2d73bJli38LFpfLpauvvlrvv/++GjVqZH8IC7YbOHCgVaVKFWvjxo25LktKSrKqVKliDRo0qOCD4YKVKlXK2rFjR67lO3bssEqVKmUgkfPFxsbme4qLizOWy+12W3/88Ueu5QcOHLDcbreBRKfk5ORYQ4cOtSpWrGgFBQVZycnJlmVZVv/+/a333nvPWC7Lsiyv12vt3LnTsizLCg0N9Wfbs2eP5fF4TEYrFBgTLj9t2rSxZsyYkWv5xx9/bLVq1argA+XhyJEjeb7XmVK/fn3rmmuu8Z/q169vVahQwQoKCrImTpxoLNeoUaOsmTNn+s937NjRcrvd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tWv1wQcfGMvQvHlzvfTSS7rnnnsCln/xxRcaNWqUfvjhhwLPtGbNGl177bUKCgrK8/KsrCzNnTtX999/v605mPq9AIwYMUIjRoxQ8+bNNWPGDC1fvlxffPGFhg4dKrfbrTfeeEP9+/fXO++8Yzqq43zzzTfq3Llznh94TX7gfO655/Tiiy8qLS1NderUyfVtal4HKy3qHn30Ud1www0aMmSIrrzyStNx/CpUqKCDBw8qJiZGVapU0Q8//KB69epp9+7duY5JU5C6dOmi4OBgzZs3z7FTNv/666+aMWOGZsyYoZ9//llNmzbV22+/bTqW4zlxTMjMzPRPtZ3XAavPZGpKbsm5Y0K7du20du1aR5StwvJa9uzZ0/9z27Zt9csvv2jdunWqVq2a0TE0NDRU6enpqlKlihYuXKhevXpJkooXL+7YtTO33nqrEhISCrxsbdq0yf9zjx499Pzzz2vnzp1q0qSJJOmHH37Q22+/rVGjRhVortOaNm2qffv2+Q/m7fV6lZSU5P9/+ueff6pTp062ly322SoA1apV809V++OPP1putztgKsqvv/7aqlKliql4jlatWjXrmWeesdLS0kxHCfDXSTGYIOPvdevWzapevbrldrutypUrWw8//LA1efJka/v27cZzOXEfkJIlS1pbt241dv9n8+6771otW7a03G63dfXVV1sjR440vi9DYeLEMcHtdlt//PGHZVlWwKQdZ56c8P7m1DHhvffes6pUqWINGjTImj17tv/wFqdPBakwvJbZ2dlWmzZtjL//5+Whhx6yGjRoYHXr1s0qWbKkdeDAAcuyLGvu3LlW7dq1DafL26uvvmrFxMQU+P2e/js622cik39rLpfL/3/BsgIPF2FZlpWWlma5XC77c1gWmxHazePxaOfOnf4DWHo8Hm3atMm/Xetvv/2muLi4XAf0w6lvITZs2OCoNSGStHfv3rNeHhMTU0BJCp/ffvtN//d//6dly5Zp2bJl2r59u6Kiooxtn3+2fUCeeuophYSEGMnVqFEjjR8/Xtdff72R+z+b6OhoderUSQ8//LDq1atnOk6h48QxYdmyZWrevLmCg4O1bNmys163VatWBZQqN6eOCW63O9/LCnqNW2F5LcuVK6eVK1eqevXqxjLk5c8//9SAAQOUmpqqf/zjH2rXrp0kadCgQQoJCdErr7xiLNs111wT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DXXq1EknT56UJK1evVrdunXTP//5TyUlJemGG27Q8OHDz3qfWVlZyszMDDgBAIomn3IkiTEBAHBegk0HOBf33ntvwPkpU6aoXLly2rJli0JDQyVJvXv31u233y5JGjJkiK6++mrt3LlTV111lSZMmKBbbrlFL7/8siSpRo0aWrlypb755pt87zMxMVFDhgyx6REBAAqTvdohSYqOjjacBABQmBSKNVs7duxQp06dVLVqVXm9XsXGxkqSUlJS/NepW7eu/+eoqChJ0v79+yVJW7duVePGjQNus2nTpme9z4SEBGVkZPhPqampl+KhAAAKoRhVlySlpqYyJgAAzlmhWLN15513KiYmRpMnT1bFihXl8/kUHx+v7Oxs/3WKFSvm/9nlcklSwGaG58vj8cjj8Vx4aADAZcOtIEmS1+uV1+s1nAYAUFg4vmylp6dr27Ztmjx5slq0aCFJWr58+XndRq1atbR69eqAZT/88MMlywgAAAAAf+X4slW6dGlFRkZq0qRJioqKUkpKivr27Xtet9GjRw81b95cY8eO1d13360FCxacdX8tAAAAALhYjt9ny+12a+bMmVq3bp3i4+PVs2dPjRkz5rxuo0mTJpo8ebImTJigevXqaeHCherfv79NiQEAAACgEKzZkqS2bdtqy5YtAcssy8rzZ0mKiIjItaxr167q2rVrwLIXX3zxEicFAAAAgFMcv2YLAAAAAAojyhYAAAAA2ICyBQAAAAA2oGwBAAAAgA0oWwAAAABgA8oWAAAAANiAsgUAAAAANqBsAQAAAIANKFsAAAAAYAPKFgAAAADYgLIFAAAAADagbAEAAACADYJNByhs0m45KXeJk6ZjBKiV8JvpCPkK/S3KdIS8NalrOkH+fthkOgGAc+SLriBfkMd0jACuH342HSFf7pBipiPk6etrHTpWSfp3T2c+Z91Hp5uOkK9vGvDx9nxZJ5z12fZywpotAAAAALABZQsAAAAAbEDZAgAAAAAbULYAAAAAwAaULQAAAACwAWULAAAAAGxA2QIAAAAAG1C2AAAAAMAGlC0AAAAAsAFlCwAAAABsQNkCAAAAABtQtgAAAADABpQtAAAAALABZQsAAAAAbEDZAgAAAAAbULYAAAAAwAZFqmx98803uv766xUREaHIyEjdcccdSk5ONh0LAAAAwGWoSJWtI0eOqFevXlq7dq2WLFkit9ut9u3by+fzmY4GAAAA4DITbDpAQbr33nsDzk+ZMkXlypXTli1bFB8fH3BZVlaWsrKy/OczMzMLJCMAwHl8ypH037GAMQEAcC6K1JqtHTt2qFOnTqpataq8Xq9iY2MlSSkpKbmum5iYqPDwcP8pOjq6gNMCAJxir3ZIkqKjoxkTAADnrEiVrTvvvFMHDx7U5MmTtXr1aq1evVqSlJ2dneu6CQkJysjI8J9SU1MLOi4AwCFiVF2SlJqaypgAADhnRWYzwvT0dG3btk2TJ09WixYtJEnLly/P9/oej0cej6eg4gEAHMytIEmS1+uV1+s1nAYAUFgUmbJVunRpRUZGatKkSYqKilJKSor69u1rOhYAAACAy1SR2YzQ7XZr5syZWrduneLj49WzZ0+NGTPGdCwAAAAAl6kis2ZLktq2bastW7YELLMsy1AaAAAAAJezIrNmCwAAAAAKEmULAAAAAGxA2QIAAAAAG1C2AAAAAMAGlC0AAAAAsAFlCwAAAABsQNkCAAAAABtQtgAAAADABpQtAAAAALABZQsAAAAAbEDZAgAAAAAbULYAAAAAwAbBpgMUNrEzLAUHW6ZjBDjYOtZ0hHyVSss2HSFPRyuWMB0hX2HlrzAdIU85f+w3HQFwHF/xIPmCnTWUBntDTUfIl+/IMdMR8uQuUdx0hHxFbj1pOkKeant+Mx0hX4vKXGU6Qp5O7kszHaHwcQeZTpA3yyf5zu2qrNkCAAAAABtQtgAAAADABpQtAAAAALABZQsAAAAAbEDZAgAAAAAbULYAAAAAwAaULQAAAACwAWULAAAAAGxA2QIAAAAAG1C2AAAAAMAGlC0AAAAAsAFlCwAAAABsQNkCAAAAABtQtgAAAADABpQtAAAAALABZQsAAAAAbEDZAgAAAAAbXFTZmjdvniIiIpSTkyNJSkpKksvlUt++ff3XeeKJJ/TII49Ikj7//HNdffXV8ng8io2N1bhx4wJuLzY2VsOHD9ejjz6q0NBQxcTE6Msvv9S///1v3X333QoNDVXdunW1du1a/++kp6erU6dOqlSpkkqWLKk6derok08+Cbjd1q1bq0ePHnr55ZdVpkwZVahQQYMHD76Yhw4AAAAAZ3VRZatFixY6dOiQNmzYIElatmyZypYtq6VLl/qvs2zZMrVu3Vrr1q3T/fffrwcffFA//fSTBg8erAEDBmjq1KkBtzl+/Hg1b95cGzZs0O23367OnTvr0Ucf1SOPPKL169fryiuv1KOPPirLsiRJx48f17XXXquvvvpKP//8s5588kl17txZa9asCbjdadOmqVSpUlq9erVGjx6toUOHatGiRfk+tqysLGVmZgacAABFk0+nvlRkTAAAnI+LKlvh4eGqX7++v1wtXbpUPXv21IYNG3T48GH99ttv2rlzp1q1aqXXXntNN954owYMGKAaNWqoS5cu+uc//6kxY8YE3OZtt92mp556StWrV9fAgQOVmZmpRo0aqWPHjqpRo4b69OmjrVu36o8//pAkVapUSb1791b9+vVVtWpVPffcc7rllls0a9asgNutW7euBg0apOrVq+vRRx9Vw4YNtWTJknwfW2JiosLDw/2n6Ojoi3mqAACF2F7tkCRFR0czJgAAztlF77PVqlUrLV26VJZl6fvvv1eHDh1Uq1YtLV++XMuWLVPFihVVvXp1bd26Vc2bNw/43ebNm2vHjh3+zRClU6XotPLly0uS6tSpk2vZ/v37JUk5OTkaNmyY6tSpozJlyig0NFQLFixQSkpKwH2debuSFBUV5b+NvCQkJCgjI8N/Sk1NPZ+nBQBwGYlRdUlSamoqYwIA4JwFX+wNtG7dWlOmTNHGjRtVrFgxXXXVVWrdurWWLl2q//znP2rVqtV53V6xYsX8P7tcrnyX+Xw+SdKYMWM0YcIEvf7666pTp45KlSqlF154QdnZ2fne7unbOX0befF4PPJ4POeVHQBweXIrSJLk9Xrl9XoNpwEAFBYXvWbr9H5b48eP9xer02Vr6dKlat26tSSpVq1aWrFiRcDvrlixQjVq1FBQUNAF3/+KFSt0991365FHHlG9evVUtWpVbd++/YJvDwAAAAAuhYsuW6VLl1bdunX18ccf+4tVy5YttX79em3fvt1fwF588UUtWbJEw4YN0/bt2zVt2jS99dZb6t2790Xdf/Xq1bVo0SKtXLlSW7du1VNPPeXfnwsAAAAATLkkx9lq1aqVcnJy/GWrTJkyql27tipUqKCaNWtKkho0aKBZs2Zp5syZio+P18CBAzV06FB16dLlou67f//+atCggdq1a6fWrVurQoUKuueeey7uAQEAAADARbrofbYk6fXXX9frr78esCwpKSnX9e69917de++9+d7Onj17ci07PcX7abGxsQHL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",
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['a man and a woman eating the evening.']\n"
     ]
    }
   ],
   "source": [
    "sentence_list = [\n",
    "    \"Mann in einem kleinen weißen Boot auf einem See.\",  # Man in a small white boat on a lake.\n",
    "    \"Ein Mann mit einem Eimer und ein Mädchen mit einem Hut am Strand.\", # A man with a bucket and a girl in a hat on the beach.\n",
    "    \"Drei Männer auf Pferden während eines Rennens.\",  # Three men on horses during a race.\n",
    "    \"Ein Mann und eine Frau essen zu Abend\",  # 一个男人和一个女人在吃晚餐\n",
    "]\n",
    "\n",
    "# load checkpoints\n",
    "model = TransformerModel(config)\n",
    "model.load_state_dict(state_dict)\n",
    "translator = Translator(model.cpu(), tokenizer, tokenizer)\n",
    "# 分开翻译sentence_list中的句子\n",
    "for sentence in sentence_list:\n",
    "    print(translator([sentence]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "acbc10a76aa5532f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-03-13T12:20:32.408600Z",
     "iopub.status.busy": "2025-03-13T12:20:32.408121Z",
     "iopub.status.idle": "2025-03-13T12:20:32.541986Z",
     "shell.execute_reply": "2025-03-13T12:20:32.541428Z",
     "shell.execute_reply.started": "2025-03-13T12:20:32.408574Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "translate-transformer-not-share\n"
     ]
    }
   ],
   "source": [
    "!ls checkpoints"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
